2013-02-11 86 views
1

爲什麼X值低於always =值爲「int.Parse(radTextBoxFloodRequests.Text)」而不是值i?值總是相同

C#代碼

private void radButtonTaskWithStatus_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     Task<int>[] tasks = new Task<int>[int.Parse(radTextBoxFloodRequests.Text)]; 

     for (int i = 0; i < int.Parse(radTextBoxFloodRequests.Text); i++) 
     { 
      tasks[i] = new Task<int>(() => 
      { 
       int x = i; 
       int result = TaskRequestWithResult(int.Parse(radTextBoxFirstNumber.Text), int.Parse(radTextBoxSecondNumber.Text), int.Parse(radTextBoxFloodDelay.Text), x); 
       return result; 
      }); 
     } 

     var continuation = Task.Factory.ContinueWhenAll(
        tasks, 
        (antecedents) => 
        { 

         int total = 0; 
         for (int i = 0; i < int.Parse(radTextBoxFloodRequests.Text); i++) 
          total = total + tasks[i].Result; 
         Debug.Print("Finished - Sum of all results is: " + total); 
         MessageBox.Show("Finished - Sum of all results is: " + total);      
        }); 


     for (int i = 0; i < int.Parse(radTextBoxFloodRequests.Text); i++) 
      tasks[i].Start(); 
     // Use next line if you want to block the main thread until all the tasks are complete 
     //continuation.Wait(); 


    } 
    catch (Exception ex) 
    { 

     MessageBox.Show(ex.Message.ToString()); 

    } 
} 

回答

6

您要關閉在循環值。您需要將臨時變量移動到外部範圍:

for (int i = 0; i < int.Parse(radTextBoxFloodRequests.Text); i++) 
    { 
     int x = i; // This was in the wrong scope 
     tasks[i] = new Task<int>(() => 
     { 
      int result = TaskRequestWithResult(int.Parse(radTextBoxFirstNumber.Text), int.Parse(radTextBoxSecondNumber.Text), int.Parse(radTextBoxFloodDelay.Text), x); 
      return result; 
     }); 
    } 

詳情爲什麼發生這種情況,看到埃裏克利珀的Closing over the loop variable considered harmful

這就是說,在這種情況下,你正在執行序列中每個元素的「任務」。您可能需要考慮使用Parallel.For而不是一系列任務,因爲根據意圖可能會更清楚。

int firstNum = int.Parse(radTextBoxFirstNumber.Text); 
int secondNum = int.Parse(radTextBoxSecondNumber.Text); 
int delay = int.Parse(radTextBoxFloodDelay.Text); 
var task = Task.Factory.StartNew(() => 
{ 
    int total; 
    Parallel.For(0, int.Parse(radTextBoxFloodRequests.Text), 
    () => 0, 
    (i, loopState, localState) => 
    { 
     return localState + TaskRequestWithResult(firstNum, secondNum, delay, i); 
    }, 
    localTotal => Interlocked.Add(ref total, localTotal); 

    return total; 
}; 

var continuation = task.ContinueWith(
       antecedent => 
       { 

        int total = antecedent.Result; 
        Debug.Print("Finished - Sum of all results is: " + total); 
        MessageBox.Show("Finished - Sum of all results is: " + total);      
       }); // Can use scheduler here if you want to update UI values 
+0

非常感謝你 – user1438082 2013-02-11 21:49:02