. net 4.0中的任务

本文关键字:任务 net | 更新日期: 2023-09-27 18:16:23

我正在尝试在。net 4.0 c#中使用任务进行并行编程。

程序的输出有点混乱。

 class Program
    {
        static void Main(string[] args)
        {
            List<Task> lstTasks =  new List<Task>();
            for (int i = 0; i < 5; i++)
            {
                Task tsk = Task.Factory.StartNew(() => DoSomething(i.ToString()));
                lstTasks.Add(tsk);
            }
            Task.WaitAll(lstTasks.ToArray());
            Console.WriteLine("Done");
            Console.ReadLine();
        }
        static void DoSomething(string tasKname)
        {
            Console.WriteLine(tasKname);
            System.Threading.Thread.Sleep(10000);
        }
    }

输出

5
5
5
5
5
Done.

我期待。

0
1
2
3
4
Done.

我哪里错了?

. net 4.0中的任务

在定义函数() => DoSomething(i.ToString())时创建了一个闭包。

闭包是一个匿名函数,它引用了在创建闭包的方法中定义的一些变量。在您的例子中,这是变量i

当这个函数被执行时,它将使用i的当前值,而不是创建i时的值。

您必须意识到调用Task.Factory.StartNew不会立即开始执行任务。在您的示例中,任务在for循环之后开始执行,因此i的值为5。

要得到预期的结果,在循环中使用一个单独的变量来存储i的当前值。

for (int i = 0; i < 5; i++)
{
    int k = i;
    Task tsk = Task.Factory.StartNew(() => DoSomething(k.ToString()));
    lstTasks.Add(tsk);
}

您正在访问一个在循环中不断变化的变量。实际上,您的foreach运行得非常快,当DoSomething运行时,i已经是5了。试试这个:

for (int i = 0; i < 5; i++)
{
    Task tsk = Task.Factory.StartNew(() => DoSomething(i.ToString()));
    lstTasks.Add(tsk);
    Thread.Sleep(50);
}

,您应该在控制台中看到预期的输出。


你说I'm expecting 0 1 2 3 4。但你不应该。任务最重要的方面是你不知道它们什么时候会完成。例如,当我修改代码使用Parallel.Foreach():

Parallel.ForEach(Enumerable.Range(0, 5), i =>
{
    Task tsk = Task.Factory.StartNew(() => DoSomething(i.ToString()));
    lstTasks.Add(tsk);
});

我得到预期的数字,从0到4,但每次我运行代码时都是随机顺序的,因为我们使用的是Tasks,它们都是相互独立运行的。