.Net 4.0 Task thread output is only last item added
I've created what I thought was a simple app using the .Net 4.0 Task class for threading.
Here's the code:
var services = new List<KeyValuePair<int, string>>();
services.Add(new KeyValuePair<int, string>(1, "S1"));
services.Add(new KeyValuePair<int, string>(2, "S2"));
services.Add(new KeyValuePair<int, string>(3, "S3"));
foreach (var service in services)
{
// if the running tasks don't currently include this service, add it
if (!htTasks.ContainsKey(service.Key))
{
tempTask = Task.Factory.StartNew(() => DoSomeWork(service.Value));
htTasks.Add(service.Key, tempTask);
Console.WriteLine("New service added: " + service.Value);
}
else
{
Console.WriteLine("No new services found");
}
}
I'm trying to dynamically create threads to do a task based on a list (which will eventually be coming from a database). The actual task is just to print to the console:
public static void DoSomeWork(string threadName)
{
Console.WriteLine("Work done: " + threadName);
}
However, I get the following output - which suggests only the last thread I add is running:
New Service added: S1
New Service added: S2
New Service add开发者_Go百科ed: S3
Work done: S3
Work done: S3
Work done: S3
Think I must be doing something wrong with creating the threads. Any help appreciated.
You're capturing the loop variable (service
) in a lambda expression. Don't do that :)
(Follow the link to find out details of what's going on.)
It's easy to fix - copy the loop variable and capture the copy:
foreach (var service in services)
{
var copy = service;
// if the running tasks don't currently include this service, add it
if (!htTasks.ContainsKey(service.Key))
{
tempTask = Task.Factory.StartNew(() => DoSomeWork(copy.Value));
htTasks.Add(service.Key, tempTask);
Console.WriteLine("New service added: " + service.Value);
}
// code as before
}
As a separate note, you haven't declared tempTask
anywhere in the code you've shown - personally I wouldn't bother with it - I'd use:
htTasks[service.Key] = Task.Factory.StartNew(() => DoSomeWork(copy.Value));
Note that in C# 5 this "copying" is likely to become unnecessary - Eric Lippert has indicated a few times that the behaviour will probably change to be the more expected "each loop iteration has a separate variable".
精彩评论