同时处理超过64个线程

时间:2013-08-07 12:13:31

标签: vb.net multithreading threadpool

我正在阅读有关Thread pooling in VB的教程。 Fibonacci计算有一个例子:

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错误?

4 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

如果要等待X> 63的X任务完成,请使用倒计时:ONE atomic int和ONE MRE。将int初始化为[no。的任务],启动你的任务,并使用WaitForSingleObject()/ WaitOne()等待MRE。当任务完成时,它以原子方式递减int。在任何线程上运行的任何将其递减为零的任务都会向MRE发出信号。

实际上,对X&lt; 63:)

使用此机制

答案 2 :(得分:0)

可能是您的系统在WaitHandle中不能支持超过64个对象,请参见此处:

http://msdn.microsoft.com/en-us/library/z6w25xa6.aspx

您可以在此处找到此问题的解决方法:

Workaround for the WaitHandle.WaitAll 64 handle limit?

然而,正如其他答案所述,无论如何,你可能无法获得这么多线程。

答案 3 :(得分:0)

在具有4个核心或2个核心的计算机上使用这么多线程没有任何实际优势。理想情况下,您确实只需要与核心数相同的线程数。

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

线程池的要点是告诉你的系统 maximally 使用一定数量的线程,并将剩下的线程留给系统来确定什么是最好的。