.Net 4.0中的任务

时间:2015-10-06 19:40:08

标签: c# .net c#-4.0 multitasking

我尝试使用.Net 4.0 c#中的Task进行并行编程。

我的程序输出有点混乱。

 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.

我出错了?

2 个答案:

答案 0 :(得分:2)

您在定义函数() => DoSomething(i.ToString())时创建了closure

闭包是一个匿名函数/ lamdba,它引用了创建闭包的方法中定义的一些变量。在您的情况下,这是变量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);
}

你不应该以任何特定的顺序期待结果。

答案 1 :(得分:2)

您正在访问正在循环中更改的变量。从本质上讲,您的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都是相互独立运行的。{/ p>