2

タイトルは、このエラーが発生している他の人がこれを簡単に見つけられるようにするためのものです。私はスレッディングに不慣れなので、これは本当に私に一体感を与えています。カッシーニをクラッシュさせるこのランタイムエラーが発生します。これは、もともとVS 2003でWebサイトプロジェクトとして開発され、VS2008Webサイトプロジェクトに変換されたコードです。

重要な情報:

  • この場合、配列内のオブジェクトの数manualEventsは128です。
  • products文字列の配列です
  • .NET2.0をサポートする必要があります
For Each product As String In products
    If Not product.Trim().ToUpper().EndsWith("OBSOLETE") Then
        calls += 1
    End If
Next
Dim results(calls - 1) As DownloadResults
'Dim manualEvents(calls - 1) As Threading.ManualResetEvent '128 objects in this case.
Dim manualEvents(0) As Threading.ManualResetEvent
manualEvents(0) = New Threading.ManualResetEvent(False)
'NOTE: I don't think this will work because what is not seen here, is that
'    this code is being used to populate and cache a long list of products,
'    each with their own category, etc. Am I misunderstanding something?

'initialize results structures
'spawn background workers
calls = 0
For Each product As String In products
    If Not product.Trim().ToUpper().EndsWith("OBSOLETE") Then
        Dim result As New DownloadResults

        'manualEvents(calls) = New Threading.ManualResetEvent(False)
        'Moved above For Each after declaration of variable

        result.params.product = product
        result.params.category = docType
        'result.ManualEvent = manualEvents(calls)
        result.ManualEvent = manualEvents(0)
        result.Context = Me._context

        results(calls) = result

        Threading.ThreadPool.QueueUserWorkItem(AddressOf ProcessSingleCategoryProduct, results(calls))
        Threading.Interlocked.Increment(calls) 'Replaces below incrementation

        'calls += 1
    End If
Next

Threading.WaitHandle.WaitAll(manualEvents) 'CRASHES HERE

スレッドヘルパー関数(完了のため)

Public Shared Sub ProcessSingleCategoryProduct(ByVal state As Object)
    Dim drs As DownloadResults = CType(state, DownloadResults)
    Dim adc As New cADCWebService(drs.Context)

    drs.docs = adc.DownloadADC(drs.params.category, drs.params.product)
    drs.ManualEvent.Set()
End Sub
4

1 に答える 1

4

128スレッドすべての完了を確認するために、128個の手動イベントの配列は必要ありません。

手動リセットイベントを1つだけ作成し、128から始まる単純な整数を作成しますInterlocked.Decrement。の終わりを使用してその整数をデクリメントしProcessSingleCategoryProduct、カウントがゼロに達したときにのみイベントを通知します。

if (Interlocked.Decrement(ByRef myCounter) = 0) myEvent.Set();

Threading.ManualResetEvent次に、それらの配列ではなく1つだけを宣言すると、そのWaitOne代わりに呼び出すことができWaitAll、完了です。

.NET 4を使用している場合のより簡単な代替方法については、usrのコメントも参照してください。

于 2012-06-05T21:18:28.330 に答える