线程异常:WaitHandles的数量必须小于或等于64

时间:2012-06-05 21:09:25

标签: vb.net multithreading threadpool

标题是让其他人有这个错误很容易找到。我是Threading的新手,所以这真的让我很好。我收到了崩溃Cassini的运行时错误。这是我最初在VS 2003中作为网站项目开发并转换为VS 2008网站项目的代码。

重要信息:

  • 在这种情况下,manualEvents数组中的对象数为128。
  • products是一个字符串数组
  • 需要支持.NET 2.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

1 个答案:

答案 0 :(得分:2)

您不需要128个手动事件的数组来检查所有128个线程的完成情况。

仅创建一个手动重置事件和一个从128开始的普通整数。使用Interlocked.Decrement末尾的ProcessSingleCategoryProduct减去该整数,并仅在计数达到零时发出事件信号:

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

然后只声明一个Threading.ManualResetEvent而不是其中的数组,您可以在其上调用WaitOne而不是WaitAll,然后就完成了。

如果您有.NET 4,请参阅usr的评论,以获得更简单的替代方案。