2014-01-22 69 views
0

爲什麼導致錯誤結果的任務列表。 任何人都可以給方向?並行任務導致錯誤結果

這是我的代碼到目前爲止。

static string[] kk = new string[] { "a", "b", "c", "d", "e", "f" }; 

static void Main(string[] args) 
    { 
     //Parallel.For(0, 10, i => Test(i)); 
     //Console.ReadLine(); 

     foreach(string str in kk) 
     { 
      Task<string> task = Task.Factory.StartNew(() => Test(str)); 
      listTask.Add(task); 
     } 

     do 
     { 
      Thread.Sleep(100); 
     }while(!Task.WaitAll(listTask.ToArray(),1000)); 

     foreach (Task<string> task in listTask) 
     { 
      Console.WriteLine(task.Status.ToString() + " : " + task.Result); 
     } 

     Console.ReadLine(); 
    } 

private static string Test(string i) 
     { 
      return "test " + i; 
     } 

我期望導致這樣的:

測試一個 試驗B 試驗C 測試d 測試電子郵件 測試f

但是我上面的代碼得到的是這樣的: 測試f test f test f test f test f test f

在此先感謝。

回答

2

這條線是罪魁禍首:

Task<string> task = Task.Factory.StartNew(() => Test(str)); 

Lambda表達式,其捕獲的str變量,在運行任務時僅進行評價。

在這種情況下,任務的線程在foreach循環完成時被激活 - 這意味着Test(str)將被評估爲Test("f")所有六個調用。發生這種情況是因爲foreach實現爲所有迭代重用str變量,因此所有六個lambda表達式都捕獲相同的變量。

嘗試將其更改爲:

var localStr = str; 
Task<string> task = Task.Factory.StartNew(() => Test(localStr)); 

使每一個表情捕捉自己的局部變量這將使。

編輯

這個問題是固定在C#5:Has foreach's use of variables been changed in C# 5?

每個foreach迭代現在得到的變量的新副本。

+0

感謝@dcastro您的指導和解釋:) –