的任务.继续和我预想的不一样
本文关键字:不一样 任务 继续 | 更新日期: 2023-09-27 18:05:03
考虑以下代码。我从一个什么都不做的任务开始,然后使用ContinueWith()开始10次调用一个增加计数器的方法。
当我运行这个程序时,它打印"0",表示根本没有调用increment()方法。我希望它被调用10次,因为这是我调用ContinueWith()的次数。
如果我取消注释"Thread.Sleep(20)"行,那么它会像预期的那样打印"10"。
这在发布或调试模式下都会发生。我的系统是一个core 2 quad,带有超线程(8个逻辑内核),运行Windows 7 x64。
我想我对Task.ContinueWith()的工作方式有一些基本的误解....
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication4
{
class Program
{
static void Main()
{
using (var task = Task.Factory.StartNew(()=>{}))
{
for (int i = 0; i < 10; ++i)
{
task.ContinueWith(_=> increment());
// Thread.Sleep(20); // Uncomment to print 10 instead of 0.
}
task.Wait();
}
// This prints 0 UNLESS you uncomment the sleep above.
Console.WriteLine(counter);
}
static void increment()
{
Interlocked.Increment(ref counter);
}
private static int counter;
}
}
谁能解释一下这里发生了什么?
原因很简单:等待已经完成的任务。您真正想要的是等待在循环中创建的十个任务:
var tasks = new List<Task>();
for (int i = 0; i < 10; ++i)
{
tasks.Add(task.ContinueWith(_=> increment()));
}
Task.WaitAll(tasks.ToArray());
当然。当初始任务完成时,您将打印出该值—而不是等待执行延续。换句话说,当初始任务完成时,会发生11件事:
- 10个新任务开始执行,每个任务增加计数器
- 你打印出计数器
如果你愿意,你可以有效地将所有这些链接在一起:
task = task.ContinueWith(_=> increment());
当原始任务完成时,将触发一个增量。当完成时,将触发下一个增量。当那结束时[…]。当最后一个增量完成后,您的Wait
调用将返回。
如果按如下方式更改主体:
using (var task = Task.Factory.StartNew(() => { }))
{
var t = task;
for (int i = 0; i < 10; ++i)
{
t = t.ContinueWith(_ => increment());
// Thread.Sleep(20); // Uncomment to print 10 instead of 0.
}
t.Wait();
}
你不睡觉就会得到10
。主要的改变是t = t.ContinueWith(...)
和t
是必要的,因为你不允许改变using()
变量。