. net 4.0任务线程输出只是添加的最后一项
本文关键字:最后 一项 添加 任务 线程 输出 net | 更新日期: 2023-09-27 18:09:07
我使用。net 4.0 Task类创建了一个我认为简单的应用程序。
代码如下:
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");
}
}
我试图动态地创建线程做一个基于列表的任务(这将最终来自数据库)。实际的任务只是打印到控制台:
public static void DoSomeWork(string threadName)
{
Console.WriteLine("Work done: " + threadName);
}
但是,我得到以下输出-这表明只有我添加的最后一个线程正在运行:
New Service added: S1
New Service added: S2
New Service added: S3
Work done: S3
Work done: S3
Work done: S3
我想我一定是做错了创建线程。
在lambda表达式中捕获循环变量(service
)。不要那样做:)(点击链接了解具体情况)
很容易修复-复制循环变量并捕获副本:
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
}
作为一个单独的注意事项,您没有在您所展示的代码中声明tempTask
-我个人不会为此烦恼-我会使用:
htTasks[service.Key] = Task.Factory.StartNew(() => DoSomeWork(copy.Value));
请注意,在c# 5中,这种"复制"可能变得不必要了——Eric Lippert已经多次指出,这种行为可能会改变为更期望的"每个循环迭代有一个单独的变量"。