vb.net - 线程异常: The number of WaitHandles must be less than or equal to 64

标签 vb.net multithreading threadpool

标题是为了让其他遇到此错误的人能够轻松找到此内容。我是线程的新手,所以这真的让我很烦恼。我收到导致卡西尼号崩溃的运行时错误。这是我维护的代码,最初是在 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

最佳答案

您不需要包含 128 个手动事件的数组来检查所有 128 个线程是否完成。

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

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

然后仅声明一个 Threading.ManualResetEvent 而不是它们的数组,并且您可以对其调用 WaitOne 而不是 WaitAll,你就完成了。

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

关于vb.net - 线程异常: The number of WaitHandles must be less than or equal to 64,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10905016/

相关文章:

ios - 为什么 weak/strong dance 解决了这个 strong reference cycle?我不明白

c# - 将 ThreadPool 与回调一起使用

asp.net - asp.net IIS 7.0 或更高版本中 maxConcurrentThreadsPerCPU 的默认值是多少?

.net - 如果在 VB.NET 中超时,如何停止/加入线程

python - 使用队列时区分线程的返回值

.net - 使用任务库进行多线程处理

vb.net - DoWork Ba​​ckgroundWorker内部的顺序过程

vb.net - Linq 嵌套分组

c# - 使用 LINQ,我可以像在 C# 中那样在 VB.NET 中为 "grouping"命名吗?

mysql - VB.net mySQL 如何在sql查询中使用DateAdd