2013-07-05 37 views
3

我在for循環中創建System.Threading.Tasks,然後在同一循環內運行ContinueWithfor循環與System.Threading.Tasks中的奇怪行爲

int[,] referencedArray = new int[input.Length/4, 5]; 
    for (int i = 0; i <= input.Length/4; i += 2048) 
    { 
     int[,] res = new int[input.Length/4, 5]; 
     int[,] arrayToReference = new int[input.Length/4, 5]; 
     Array.Clear(arrayToReference, 0, arrayToReference.Length); 
     Array.Copy(input, i, arrayToReference, 0, input.Length/4); 
     Task<Tuple<int[,], int>> test = Task.Factory.StartNew(() => addReferences(arrayToReference, i)); 
     test.ContinueWith(t => { Array.Copy(t.Result.Item1, 0, referencedArray, t.Result.Item2, input.Length/4); MessageBox.Show("yai", t.Result.Item2.ToString()); }); 
     Array.Copy(res, 0, referencedArray, i, input.Length/4); 

其中addReference sbroutine是:

public Tuple<int[,],int> addReferences(int[,] input, int index) 
    { 
      for (int i = 0; i < 2048; i++) 
      { 
       for (int j = 0; j < i; j++) 
       { 
        if ((input[i, 0] == input[j, 0]) && (input[i, 1] == input[j, 1]) && (input[i, 2] == input[j, 2]) && (input[i, 3] == input[j, 3])) 
        { 
         input[i, 4] = (j - i); 
        } 
       } 
      } 
     } 
     return new Tuple<int[,],int>(input,index); 
    } 

不過,我變得非常奇怪的結果:

1.指數(自啓動任務循環計數器產生)不知何故變得太大。我最初認爲這是因爲循環計數器增加超過其最大值,停止循環,但是當執行continueWith時,它使用了新值。但是,即使在啓動時將循環計數器的值作爲index發送到任務,錯誤仍然存​​在。 編輯:解決

我在原來的計發我的錯誤

2.對於某些原因,少於預期的任務實際完成(例如,即使85個任務預計要創建的基礎上,循環計數器最大值160,000除以2,048 = 78的迭代值,只出現77個彈出窗口) - 編輯檢查控制檯,很明顯循環計數器在突然停止之前一直增加到約157,696。

我真的很困惑任務和線程,所以如果你可以有任何的幫助,這將是非常有用的 - 在此先感謝。

編輯我已經做了道格拉斯建議的更改,它解決了我的第一個問題 - 我仍然堅持第二個問題。

+0

你試過只是做了控制檯輸出,以確保有*絕對*與線程的問題沒有完成?就我個人而言,我認爲應用程序中的70多個彈出窗口的想法是...... – James

+0

我試過控制檯輸出,並且在停止之前它又一次起來,直到157,000 – FireOak

回答

4

這可能無法完全解決您遇到的問題,但作爲一個起點,你需要複製你的循環計數器內變量,以避免在您的匿名方法引用它之前關閉問題:

for (int i = 0; i <= input.Length/4; i += 2048) 
{ 
    // ... 
    int iCopy = i; 
    var test = Task.Factory.StartNew(() => addReferences(arrayToReference, iCopy)); 
    // ... 
} 

請參閱Jon Skeet's answer(特別是鏈接的文章),解釋爲什麼這是必要的。

編輯:關於你的第二個問題,我懷疑它可能與整數除法有關。 input.Length的價值是什麼,你期待85次迭代?你說174,000除以2048應該給85,但實際上它會給84,因爲整數除法導致結果被截斷。

編輯:你沒有看到所有預期的迭代可能是你的程序,而無需等待任務(通常在後臺線程執行)來完成終止的另一個原因。檢查是否等待任務的解決您的問題:

List<Task> tasks = new List<Task>(); 
for (int i = 0; i <= input.Length/4; i += 2048) 
{ 
    // ... 
    var test = Task.Factory.StartNew(() => addReferences(arrayToReference, iCopy)); 
    tasks.Add(test); 
    // ... 
} 
Task.WaitAll(tasks); 
+0

謝謝,這解決了第一個問題 - 第二個沒有運氣我很害怕 – FireOak

+0

關於第二點 - 我不確定它是一個分部錯誤,因爲它達到了157,000,並突然停止 - 它只完成了79,這看起來太低了 – FireOak

+0

是的,但是input.Length是什麼? – Douglas