Reputation: 2748
Why is the value X below always = to the value "int.Parse(radTextBoxFloodRequests.Text)" rather than the value i?
C# Code
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());
}
}
Upvotes: 1
Views: 92
Reputation: 564931
You're closing over the loop value. You need to move your temporary variable into the outer scope:
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;
});
}
For details on why this occurs, see Eric Lippert's Closing over the loop variable considered harmful.
That being said, in this case, you're performing a "task" for each element in a sequence. You may want to consider using Parallel.For
instead of an array of tasks, as that would likely be more clear in terms of intent.
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
Upvotes: 6