0

我正在阅读有关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 次计算开始出现异常,即:

等待句柄必须小于 64

我希望这个应用程序将处理 N 个计算。一个好主意可以为线程池设置一个上限(例如:6)。N 个计算一次最多使用 6 个线程来处理。我如何编辑代码来处理这个删除waitHandle错误?

4

4 回答 4

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
于 2013-08-07T12:36:37.230 回答
1

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

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

于 2013-08-07T13:40:59.950 回答
0

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

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

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

WaitHandle.WaitAll 64 句柄限制的解决方法?

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

于 2013-08-07T12:18:08.650 回答
0

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

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

线程池的真正意义在于告诉您的系统最大限度地使用一定数量的线程,并将其余的留给系统来确定什么是最好的。

于 2013-08-07T12:19:26.493 回答