Task.ContinueWith不工作我的预期
请考虑以下代码。 我开始执行一个什么都不做的任务,然后使用ContinueWith()开始对一个递增计数器的方法进行10次调用。
当我运行该程序时,它打印“0”,表示还没有调用increment()方法。 我期待它被调用10次,因为那是我调用ContinueWith()的次数。
如果我取消注释“Thread.Sleep(20)”行,则按预期打印“10”。
这在发布或调试模式下发生。 我的系统是运行Windows 7 x64的超级线程(8个逻辑核心)的核心2 quad。
我假设我对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 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(); 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()
变量。