[英]Strange behaviour in for loop with System.Threading.Tasks
我正在for循環中創建System.Threading.Tasks
,然后在同一循環中運行ContinueWith
。
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。
我真的對任務和線程感到困惑,所以如果你能提供任何非常有用的幫助 - 請提前感謝。
編輯我做了道格拉斯建議的改變,這解決了我的第一個問題 - 我仍然堅持第二個問題。
這可能無法完全解決您遇到的問題,但作為一個起點,您需要通過將循環計數器復制到內部變量來避免關閉問題,然后再在匿名方法中引用它:
for (int i = 0; i <= input.Length/4; i += 2048)
{
// ...
int iCopy = i;
var test = Task.Factory.StartNew(() => addReferences(arrayToReference, iCopy));
// ...
}
請參閱Jon Skeet的答案 (特別是鏈接的文章),以解釋為什么這是必要的。
編輯 :關於你的第二個問題,我懷疑它可能與整數除法有關。 input.Length
的值是input.Length
,你期望85次迭代? 你說174,000除以2,048應該給85,但實際上它會給84,因為整數除法導致結果被截斷。
編輯2 :您沒有看到所有預期迭代的另一個原因可能是您的程序正在終止而不等待任務(通常在后台線程上執行)完成。 檢查等待任務是否可以解決您的問題:
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);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.