【问题标题】:Threading Exception: The number of WaitHandles must be less than or equal to 64线程异常:WaitHandles 的数量必须小于或等于 64
【发布时间】:2012-06-06 07:22:39
【问题描述】:

标题是为了让其他有此错误的人更容易找到它。我是 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

【问题讨论】:

  • 当谷歌搜索“WaitHandles 的数量必须小于或等于 64”时,会出现很多答案。
  • @usr: 是的,已经花了好几个小时看完了。就像我说的,线程新手,所以我确定我忽略了一些东西。

标签: vb.net multithreading threadpool


【解决方案1】:

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

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

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

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

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

【讨论】:

  • @JirkaHanika:是的,我已经阅读了this link,但由于我还是线程新手,所以无法理解如何将它们组合在一起。 :(
  • @Chiramisu - 您需要支持哪个 .NET 版本?
  • @JirkaHanika:.NET 2.0,对不起,我之前肯定应该指定的。
  • @Chiramisu - 然后我在答案中增加了一层细节。
  • @JirkaHanika:请耐心等待,我真的很难解决这个问题。我在上面修改了我的代码。注释掉的行被紧随其后的行替换。它仍然坏了,导致我的卡西尼不断崩溃,让我相信我做错了什么。
猜你喜欢
  • 1970-01-01
  • 2016-04-13
  • 2019-08-22
  • 2013-05-27
  • 2015-02-27
  • 2011-12-19
  • 2019-09-26
  • 2021-08-13
  • 1970-01-01
相关资源
最近更新 更多