2013-08-07 116 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 :)