线程池等待所有64 [Leadtools]

问题描述:

我知道WaitAll ManualResetEvents的限制,即64.(因为64的任何原因) 由于这个限制,当我使用SourceFolders.Count> 64.线程池等待所有64 [Leadtools]

if (Source.SubFolders.Count > 0) 
{ 
    var threadPoolDoneEvents = new ManualResetEvent[Source.SubFolders.Count]; 
    for (int i = 0; i < Source.SubFolders.Count; i++) 
    { 
     try 
     { 
      if (m_bRegisterCancelled == false) 
      { 
       threadPoolDoneEvents[i] = new ManualResetEvent(false); 
       AddSourceAgs variables = new AddSourceAgs(); 
       variables.Source = Source; 
       variables.SubFolder = Source.SubFolders[i]; 
       variables.DoneEvents = threadPoolDoneEvents[i]; 
       ThreadPool.QueueUserWorkItem(AddSourceProcess, variables); 
      } 
      else 
      { 
       break; 
      } 
     } 
     catch (System.Exception Ex) 
     { 
      FireError(this, "AddSource", this.ExBuilder.Message(ERROR_CASE_DATABASE_ADD_SOURCE_EX), Ex); 
     } 
    } 
    WaitHandle.WaitAll(threadPoolDoneEvents); 
} 

我试图替换下面的行:

WaitHandle.WaitAll(threadPoolDoneEvents); 

通过该:

foreach (var waitHandle in threadPoolDoneEvents) 
    waitHandle.WaitOne(); 

由此导致意想不到的事情发生 - 在我的情况下,100个文件中,随机20 - 30个文件完全处理,然后休息停在两者之间。 任何想法,我的概念落后?任何解决这个问题的方法?我尝试过this,但这也会导致一些随机错误,例如处理每个任务两次或类似的事情。

UPDATE 调试后,我发现任务失败,因为扔在这行代码的异常:

try 
{ 
    RasterImage image = m_codecs.Load(m_documentNameWithPath, pageNum); 
    m_codecs.Save(image, m_outputPath+ "\\\\" + pageNum.ToString("D4") + ".png", RasterImageFormat.Png, 0); 
    return true; 
} 
catch (Exception Ex) 
{ 
    m_conversionErrors.Add(Ex); 
    return false; 
} 

以下是抛出异常:

Function evaluation disabled because a previous function evaluation timed out. You must continue execution to reenable function evaluation. 

任何解决方案是否做到甚至解释这是什么?

+2

这是底层winapi函数WaitForMultipleObjects()中的一个硬性限制。从技术上讲,限制可能会增加到128,但微软拒绝修复它。当然是因为他们认为程序员不应该编写使用多于64个线程的程序。这对你的代码来说是准确的,它只会在* one *线程中表现良好。你只有一个磁盘,它不喜欢被多个线程指定。磁盘寻求可以完全杀死你的应用程序的性能。在调试时,文件系统缓存将隐藏此问题,这在生产中不会发生。 – 2014-10-16 12:55:14

您在等待这些事件不会导致任务失败。更有可能有一个你没有注意到的例外(未被捕获或吞下)。

以您的加工Task为基础,并使用Task.WaitAll。那里没有限制。你也会得到自动的错误传播。

+0

是的,有一个异常被抛出,因为任务没有成功完成。我更新了有关该例外情况的问题。 – amyn 2014-10-17 05:17:15

+0

这只是一个调试器消息。无论如何,这对这个问题并不重要。图像转换代码中存在一个错误。与任务或等待句柄无关。 – usr 2014-10-17 08:27:22

+0

是的,我能够识别错误,问题在于'm_codecs.load()'部分。但是我用'Parallel.For'替换'ThreadPool.QueueUserWorkItem()'后,问题就解决了。在'm_codecs.load()'部分没有改变任何东西。 – amyn 2014-10-20 05:28:13