【问题标题】:Handle more than 64 thread at the same time同时处理超过64个线程
【发布时间】:2013-08-07 21:42:21
【问题描述】:

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

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

【问题讨论】:

    标签: vb.net multithreading threadpool


    【解决方案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
    

    【讨论】:

    • 这样我就有了两个for循环。如果我不需要显示结果,则第二个循环仅包含 WaitOne() 函数。如果我不需要显示结果怎么办?我真的需要只为 WaitOne() 循环一个循环吗?
    • 如果您不显示或使用结果,那么合乎逻辑的做法是首先不启动线程。如果您有其他问题并考虑了一段时间,请使用该按钮。
    【解决方案2】:

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

    其实对X

    【讨论】:

      【解决方案3】:

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

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

      线程池的真正意义在于告诉您的系统最大限度地使用一定数量的线程,而剩下的则由系统决定什么是最好的。

      【讨论】:

      • 16 核机器上的两个线程可能会出现争用问题 - 这不仅仅是系统过载的问题。
      【解决方案4】:

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

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

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

      Workaround for the WaitHandle.WaitAll 64 handle limit?

      但是,正如其他答案所述,无论如何,您可能不会从拥有这么多线程中获益。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-09
        • 2016-07-20
        • 1970-01-01
        相关资源
        最近更新 更多