. 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

我想我一定是做错了创建线程。

. net 4.0任务线程输出只是添加的最后一项

在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已经多次指出,这种行为可能会改变为更期望的"每个循环迭代有一个单独的变量"。