如何正确使用Task.ContinueWith?

26

在尝试测试TPL时,我遇到了一个简单的问题。我想在控制台窗口中获取数字(从1到1000)。

这是我的代码:

class Program
{
    static void Main(string[] args)
    {
        Task.Factory.StartNew(Calculate).ContinueWith(task =>
                                                          {
                                                              Task.WaitAll();
                                                              Console.ReadKey();
                                                          });

    }

    private static void Calculate()
    {
        for (var number = 0; number < 1000; number++)
        {
            Console.WriteLine(number);
        }
    }
}

问题在于窗口只是关闭了,没有显示出任何东西。我知道我在ContinueWith方法中弄错了什么。我怀疑ContinueWith没有被执行(因为窗口在没有我的输入的情况下就关闭了),但我不知道原因。

任何建议都有帮助(尝试阅读MSDN但无济于事)。提前致谢。


“StartNew” 不是会创建一个新线程吗?因为主线程会继续执行并退出应用程序。难道不应该编写一些代码来至少保持主线程,直到后台任务完成吗? - bas
我一直认为StartNew会启动一个任务。引用MSDN的话:“创建并启动一个任务。”链接本身:http://msdn.microsoft.com/en-us/library/dd321439.aspx - zmockus
好的,它是TPL(任务并行库)的一部分,所以我猜它仍然依赖于底层线程。在主方法退出之前,您是否尝试添加Console.ReadLine?我从未尝试过任何与TPL相关的东西,但我最好的猜测是您的应用程序只是退出了,其余的实现都很好。 - bas
医生说得有道理 :). 我在单元测试中尝试了一下,他的解决方案可行。 - bas
@bas 是正确的;该任务异步在新线程上启动,该线程的存在不会防止控制从 Main 结尾掉落并终止进程。 - Eric Lippert
1个回答

36

Continuation(延续)是异步执行的。如果你进行一些简单的测试:

public static void Main(string[] args)
{
    Task.Factory.StartNew(Calculate).ContinueWith(task =>
                                                      {
                                                          Console.WriteLine("Finished!");
                                                      });
    Console.WriteLine("Press ENTER to close...");
    Console.ReadLine();
}

你会看到:

按回车键关闭...

1

2

3

...

999

完成!

因为这个任务不会阻塞进程的进行。

如果你想要阻塞主线程等待任务完成,你可以使用以下代码:

var task = Task.Factory.StartNew(Calculate);
task.Wait();

同时,它将在Wait上阻塞。


1
他们真的用TPL让生活变得轻松了...我也应该深入研究一下这个东西:)。+1,回答快速而迅速! - bas
@bas 是的,他们确实做到了 :) 我非常喜欢 TPL,特别是在 .NET 4.5 中与 asyncawait 配对使用时。还有 TPL Dataflow…… - Patryk Ćwiek
谢谢。现在我明白了这背后的基本思想。 :) - zmockus
当出现错误时,我需要注意任何额外的事情吗? - Flimtix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接