1

スレッドプールの例をいくつか試しました。MSDN Web サイトのフィボナッチの例から始めましたが、これは 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 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()ますが、問題は次のとおりです。結果を表示する必要がない場合、2 番目のループは必要ありませんが、waitOne()関数を配置する必要がある 2 番目のループは必要ありません。 ?

4

1 に答える 1

3

あなたのコードは本質的にこれを行います:

// 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。そして、イベントを待つつもりがないなら、イベントを開催する必要ありませんよね? なぜ計算を行ってから結果を使用しないのか疑問に思うかもしれませんが。

于 2013-08-08T14:40:09.857 に答える