2013-08-07 83 views
0

我正在阅读关于Thread pooling in VB的教程。有与斐波那契数计算的例子:同时处理超过64个线程

Imports System.Threading 

Module Module1 

Public Class Fibonacci 
    Private _n As Integer 
    Private _fibOfN 
    Private _doneEvent As ManualResetEvent 

    Public ReadOnly Property N() As Integer 
     Get 
      Return _n 
     End Get 
    End Property 

    Public ReadOnly Property FibOfN() As Integer 
     Get 
      Return _fibOfN 
     End Get 
    End Property 

    Sub New(ByVal n As Integer, ByVal doneEvent As ManualResetEvent) 
     _n = n 
     _doneEvent = doneEvent 
    End Sub 

    ' Wrapper method for use with the thread pool. 
    Public Sub ThreadPoolCallBack(ByVal threadContext As Object) 
     Dim threadIndex As Integer = CType(threadContext, Integer) 
     Console.WriteLine("thread {0} started...", threadIndex) 
     _fibOfN = Calculate(_n) 
     Console.WriteLine("thread {0} result calculated...", threadIndex) 
     _doneEvent.Set() 
    End Sub 

    Public Function Calculate(ByVal n As Integer) As Integer 
     If n <= 1 Then 
      Return n 
     End If 
     Return Calculate(n - 1) + Calculate(n - 2) 
    End Function 

End Class 


<MTAThread()> 
Sub Main() 
    Const FibonacciCalculations As Integer = 9 ' 0 to 9 

    ' One event is used for each Fibonacci object 
    Dim doneEvents(FibonacciCalculations) As ManualResetEvent 
    Dim fibArray(FibonacciCalculations) As Fibonacci 
    Dim r As New Random() 

    ' Configure and start threads using ThreadPool. 
    Console.WriteLine("launching {0} tasks...", FibonacciCalculations) 

    For i As Integer = 0 To FibonacciCalculations 
     doneEvents(i) = New ManualResetEvent(False) 
     Dim f = New Fibonacci(r.Next(20, 40), doneEvents(i)) 
     fibArray(i) = f 
     ThreadPool.QueueUserWorkItem(AddressOf f.ThreadPoolCallBack, i) 
    Next 

    ' Wait for all threads in pool to calculate. 
    WaitHandle.WaitAll(doneEvents) 
    Console.WriteLine("All calculations are complete.") 

    ' Display the results. 
    For i As Integer = 0 To FibonacciCalculations 
     Dim f As Fibonacci = fibArray(i) 
     Console.WriteLine("Fibonacci({0}) = {1}", f.N, f.FibOfN) 
    Next 
End Sub 

End Module 

我已经开始这个模块,它工作正常,这只是处理9个算了一笔账:

Const FibonacciCalculations As Integer = 9 

我已经增加限制,但这正好可以处理多达63个计算。从第64届计算引发异常谓曰:

的WaitHandle必须小于64

我想这个应用程序将处理N次计算。一个好主意可以设置一个线程池的上限(例如:6)。 N个计算将一次处理最多6个线程。我怎样才能编辑代码来处理这个消除waitHandle错误?

回答

1

winapi限制你可以在同一时间等待的句柄数量是一个相当困难的限制。这仅仅是没有必要的,如果你等待每一个单独你会得到完全相同的结果:

' Wait for all threads in pool to calculate. 
For i As Integer = 0 To FibonacciCalculations 
    doneEvents(i).WaitOne() 
Next 

,并注意有你现在可以用下一个循环相结合这一点,让你的程序更有效,因为你重叠用显示计算。所以,你真的要转而青睐这样的:

' Display the results. 
For i As Integer = 0 To FibonacciCalculations 
    doneEvents(i).WaitOne() 
    Dim f As Fibonacci = fibArray(i) 
    Console.WriteLine("Fibonacci({0}) = {1}", f.N, f.FibOfN) 
Next 
+0

我需要删除等待所有? –

+1

当然可以。 –

+0

这样我有两个for循环。如果我不需要显示结果,则第二个循环包含WaitOne()函数。如果我不需要显示结果,我该怎么办?我真的需要为一个循环只用于WaitOne()? –

0

在具有4个内核或2个内核的机器上使用多个线程并没有真正的优势。理想情况下,您只需要与核心数量相同的线程数。

如果你有更多的开始失去并行性,因为线程需要将上下文切换出来让其他人运行。您也可能会遇到争用问题,具体取决于您的算法编写方式。

一个线程池的一点是真的到你的系统告诉最大使用的线程数部分,剩下的到系统要弄清楚什么是最好的。

+0

您可以在一个16芯盒获得竞争问题有两个线程 - 它不只是一个系统超载的问题。 –

1

如果你想等待X任务的完成,其中X> 63,用倒计时:一个原子int和ONE MRE。初始化int为[no。的任务],开始你的任务,并用WaitForSingleObject()/ WaitOne()等待MRE。当任务完成时,它会自动递减整数。在任何线程上运行的任何任务将其递减为零都表示MRE。

事实上,使用这种机制X < 63 :)