2016-02-13 63 views
1
 static void Main(string[] args) 
    { 
     Program p = new Program(); 
     p.TestAsyncInLoop(); 
    } 

    private void TestAsyncInLoop() 
    { 
     var tasks = new List<Task>(); 
     for (int i = 0; i < 20; i++) 
     { 
      //tasks.Add(Task.Run(() => PrintNo(i))); 
      var ii = i; 
      tasks.Add(Task.Run(() => PrintNo(ii))); 
     } 

     Task.WaitAll(tasks.ToArray()); 
    } 

    private async Task PrintNo(int no) 
    { 
     Console.WriteLine(no); 
    } 
 static void Main(string[] args) 
    { 
     Program p = new Program(); 
     p.TestAsyncInLoop(); 
    } 

    private void TestAsyncInLoop() 
    { 
     var tasks = new List<Task>(); 
     for (int i = 0; i < 20; i++) 
     { 
      //tasks.Add(Task.Run(() => PrintNo(i))); 
      var ii = i; 
      tasks.Add(Task.Run(() => PrintNo(ii))); 
     } 

     Task.WaitAll(tasks.ToArray()); 
    } 

    private async Task PrintNo(int no) 
    { 
     Console.WriteLine(no); 
    } 

在for循環中,我調用一個異步方法「PrintNo(int no)」傳遞一個參數「i」這是值類型(int)。 當方法開始執行時,「no」的值等於在循環中最初發送的值的值(可能是20)而不是當前!我做的一個解決方案是在發送一個新變量「ii」之前複製「i」的值。這個解決方案工作得很好,但你能解釋爲什麼「i」的值是沒有將複製到同步方法中的方法嗎? (不工作的代碼//被評論)將值類型(int)傳遞給異步方法不要複製值

回答

0

你對行爲的解釋稍微偏離。你沒有在循環中調用函數。該調用在lambda內部。傳遞的參數完全可以並且是有價值的。捕獲i是問題所在。這與async無關。

自C#5以來,此問題已修復爲foreach。使用foreach

作爲一個主觀說明,我認爲for循環已經成爲大多數代碼氣味,因爲我們有LINQ。爲他們看到真正的用例是非常罕見的。我想在這裏它可以作爲一個計數循環。