2014-10-16 47 views
1

我知道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

回答

1

您在等待這些事件不會導致任務失敗。更有可能有一個你沒有注意到的例外(未被捕獲或吞下)。

以您的加工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