正确使用WaitOne()函数的原因是什么

时间:2013-08-08 13:12:25

标签: vb.net multithreading threadpool

我正在尝试一些线程池示例。我从Fibonacci example on MSDN web site开始,但是this wasn't suitable for more than 64 calculations,所以我已经解决了这段代码:

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 ThreadPoolCallBackMar(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 = 65

        ' 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.ThreadPoolCallBackMar, i)
        Next

        Console.WriteLine("All calculations are complete.")

        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

        Console.Read()
    End Sub
End Module

使用WaitOne()代替WaitAll()可以解决问题,但问题是:如果我不需要显示结果,那么我不需要第二个循环,但是......没有第二个循环,我要放waitOne()函数?

1 个答案:

答案 0 :(得分:4)

您的代码基本上是这样的:

// start a bunch of threads to do calculations

Console.WriteLine("All calculations are complete."); // This is a lie!

// Wait for the threads to exit

这里的主要问题是,当您拨打Console.WriteLine时,计算不完整。好吧,他们可能完成,但你不知道,除非你等待事件发现它已被发出信号。

WaitOne的目的是告诉您计算是否已完成。您的代码应该是这样写的:

    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.ThreadPoolCallBackMar, i)
    Next

    Console.WriteLine("All calculations are started. Waiting for them to complete.")

    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

    Console.WriteLine("All calculations are complete.")

必须检查事件以了解计算完成。

现在,如果您不需要知道计算是否完成,那么根本不需要WaitOne。如果你不打算等待活动,那么 事件就没有了真正的需要,是吗?虽然有人想知道你为什么要进行计算然后不使用结果。