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()变量。