. 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.
我哪里错了?
在定义函数() => 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
,它们都是相互独立运行的。