Task.ContinueWith不工作我的预期

时间:2011-08-09 14:08:44

标签: c# task

请考虑以下代码。我开始执行一项什么都不做的任务,然后使用ContinueWith()开始对一个递增计数器的方法进行10次调用。

当我运行该程序时,它打印“0”,表示还没有调用increment()方法。我期待它被调用10次,因为那是我调用ContinueWith()的次数。

如果我取消注释“Thread.Sleep(20)”行,则按预期打印“10”。

在发布或调试模式下都会发生这种情况。我的系统是一个核心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;
    }
}

任何人都可以了解这里发生的事情吗?

3 个答案:

答案 0 :(得分:9)

原因很简单:您等待已经完成的任务。你真正想要的是等待你在循环中创建的十个任务:

var tasks = new List<Task>();
for (int i = 0; i < 10; ++i)
{
    tasks.Add(task.ContinueWith(_=> increment()));
}

Task.WaitAll(tasks.ToArray());

答案 1 :(得分:4)

不确定。您在初始任务完成时打印出值 - 您不是在等待继续发生。换句话说,当初始任务完成时,会发生11件事:

  • 10个新任务开始执行,每个任务递增计数器
  • 您打印出计数器

如果您愿意,可以将所有这些链接在一起:

task = task.ContinueWith(_=> increment());

然后当原始任务完成时,将触发一个增量器。当 完成时,下一个增量器将会触发。什么时候结束[...]。当最终的增量器完成后,您的Wait呼叫将返回。

答案 2 :(得分:3)

如果您按如下方式更改主体:

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