Pass and Retrieve Data From Task
When you use a lambda expression to create a delegate, you have access to all the variables that are visible at that point in your source code.
Accessing ForEach Variables
In foreach loop
it captures the value as it mutates after each iteration.
Code Syntax
List<Task> tasks = new List<Task>();
string[] urls = Enumerable.Range(1, 10).Select(x => "Url-" + x.ToString()).ToArray();
foreach(var url in urls)
{
tasks.Add(Task.Factory.StartNew(() => Console.WriteLine($"Data: {url}")));
}
Task.WaitAll(tasks.ToArray());
/*
Result - The order may vary
Data: Url-2
Data: Url-1
Data: Url-5
Data: Url-3
Data: Url-8
Data: Url-9
Data: Url-10
Data: Url-6
Data: Url-7
Data: Url-4
*/
Accessing For Loop Variables
However in for loop
it only captures the final value, not the value as it mutates after each iteration.
Code Syntax
Task[] taskArray = new Task[10];
for(int i = 0; i < 10; i++)
{
taskArray[i] = Task.Factory.StartNew(() => Console.WriteLine($"Data: {i}"));
}
Task.WaitAll(taskArray);
/*
Result
Data: 10
Data: 10
Data: 10
Data: 10
Data: 10
Data: 10
Data: 10
Data: 10
Data: 10
Data: 10
*/
Pass Custom Data
You can pass custom data to the state parameter of Task.Factory.StartNew
method.
class CustomData
{
public int Index;
public int ThreadId;
}
Task[] taskArray = new Task[10];
for(int i = 0; i < 10; i++)
{
taskArray[i] = Task.Factory.StartNew((Object obj) => {
var data = obj as CustomData;
data.ThreadId = Thread.CurrentThread.ManagedThreadId;
}, new CustomData { Index = i});
}
Task.WaitAll(taskArray);
Retrieve Data through AsyncState
foreach (var task in taskArray)
{
var data = task.AsyncState as CustomData;
Console.WriteLine($"ThreadId {data.ThreadId} Index: {data.Index}");
}