.Net 4.0 中的任务
Task in .Net 4.0
我正在尝试使用 .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.
我哪里错了?
您在定义函数 () => DoSomething(i.ToString())
时创建了一个 closure。
闭包是一个匿名的 function/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);
}
尽管如此,您不应该期望结果以任何特定顺序排列。
您正在访问一个在循环中发生变化的变量。本质上,你的 foreach
运行s 如此之快,到 DoSomething
运行s 时,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
都是 运行 独立的彼此的。
我正在尝试使用 .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.
我哪里错了?
您在定义函数 () => DoSomething(i.ToString())
时创建了一个 closure。
闭包是一个匿名的 function/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);
}
尽管如此,您不应该期望结果以任何特定顺序排列。
您正在访问一个在循环中发生变化的变量。本质上,你的 foreach
运行s 如此之快,到 DoSomething
运行s 时,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
都是 运行 独立的彼此的。