2010-10-14 20 views
2

我使用BlockingCollection作爲生產者消費者模式,我得到了一個例外,我認爲在它上面寫了一個專利 - 在google中只有兩個結果! 的厚望是「CompleteAdding可以不被添加到集合同時使用」和跟隨它發生在我TryAdd上個BlockingCollection:對於.net 4.0上BlockingCollection的非常特殊的例外

public void EnqueueTask(T item) 
    { 
     if (!_cancellationTokenSource.IsCancellationRequested) 
     { 
      _workerQueue.Add(item); 
     } 
    } 

CompleteAdding是呼籲消費者,生產者包裝類的Dispose :

public void Dispose() 
    { 
     if (!_IsActive) 
      return; 
     _IsActive = false; 
     _cancellationTokenSource.Cancel(); 
     _workerQueue.CompleteAdding(); 
     // Wait for the consumer's thread to finish. 
     for (int i = 0; i < _workers.Length; ++i) 
     { 
      Task t1 = Task.Factory.StartNew(() => 
      { 
       try 
       { 
        if (!_workers[i].Join(4000)) 
         LogWriter.Trace("Failed to join thread", "ThreadFailureOnDispose"); 
       } 
       catch (Exception ex) 
       { 
        OnLogged(ex.Message + ex.StackTrace); 
       } 
      }); 

     } 


     // Release any OS resources. 
    } 

微軟的任何人都有想法?我應該在取消之後並在致電CompleteAdding之前睡覺嗎?

+0

什麼是異常的類型?該文檔說'Add'(和'TryAdd')會在'CompleteAdding'被調用後嘗試添加一個項目時拋出'InvalidOperationException'。你的描述不太清楚,但如果你在'Add'調用中遇到異常,我懷疑就是這樣。 – 2013-07-31 00:08:35

回答

5

看看這塊代碼:

for (int i = 0; i < _workers.Length; ++i) 
    { 
     Task t1 = Task.Factory.StartNew(() => 
     { 
      try 
      { 
       if (!_workers[i].Join(4000)) << == Here 
        LogWriter.Trace("Failed to join thread", "ThreadFailureOnDispose"); 
      } 

_workers[i].Join(4000)i值是不是你認爲它是。再試一次:

for (int i = 0; i < _workers.Length; ++i) 
    { 
     int j = i; // copy 
     Task t1 = Task.Factory.StartNew(() => 
     { 
      try 
      { 
       if (!_workers[j].Join(4000)) // j 
        LogWriter.Trace("Failed to join thread", "ThreadFailureOnDispose"); 
      } 

在您的版本中,變量'i'被捕獲,所有任務使用相同的變量。除了前幾個以外的所有內容都會看到i == _workers.Length,因爲它們是在for循環完成後執行的。

這是一個經典的lambda + capture var問題。

+2

啊,經典的捕獲迭代變量。好點。 – 2010-10-14 20:20:01

+0

它不是真正的問題,但如果你的意思是++我而不是i ++ - 這是一個錯字。 – user437631 2010-10-14 20:21:19

+0

@user - 在foreach中獲取我的副本;只涉及該副本。 – 2010-10-14 20:21:23