C# Task.ContinueWith()父任务不';不要等待子任务完成

C# Task.ContinueWith()父任务不';不要等待子任务完成,c#,.net,multithreading,c#-4.0,task-parallel-library,C#,.net,Multithreading,C# 4.0,Task Parallel Library,因为我在嵌套任务的上下文中理解了任务,所以我真的不明白-为什么第三次打印要在第二次打印之前进行 尽管如此,我使用了Task.WaitAll(t),它在第二行之前打印第三行 代码: public static void Main() { Task t = new Task( () => { Thread.Sleep(2000);

因为我在嵌套任务的上下文中理解了
任务
,所以我真的不明白-为什么第三次打印要在第二次打印之前进行

尽管如此,我使用了
Task.WaitAll(t)
,它在第二行之前打印第三行

代码:

public static void Main()
        {

            Task t = new Task(
                () =>
                {
                    Thread.Sleep(2000);
                    Console.WriteLine("1st print...");
                });
           t.ContinueWith(
                x =>
                {
                    Thread.Sleep(2000);
                    Console.WriteLine("2nd print...");
                },
                TaskContinuationOptions.OnlyOnRanToCompletion);

            t.Start();
            Task.WaitAll(t);

            Console.WriteLine("3rd print...");
            Console.Read();

}
输出:

public static void Main()
        {

            Task t = new Task(
                () =>
                {
                    Thread.Sleep(2000);
                    Console.WriteLine("1st print...");
                });
           t.ContinueWith(
                x =>
                {
                    Thread.Sleep(2000);
                    Console.WriteLine("2nd print...");
                },
                TaskContinuationOptions.OnlyOnRanToCompletion);

            t.Start();
            Task.WaitAll(t);

            Console.WriteLine("3rd print...");
            Console.Read();

}

您只等待
t
,而不是等待它的继续。这就是为什么这种延续将在未来某个时候进行。如果没有
控制台。Read
,它可能永远不会在进程退出之前运行

Task.WaitAll(t)
相当于
t.Wait()
(您应该使用它,因为它更惯用)


让它等待所有的延续(可能是递归的)将导致不直观的行为,并产生非局部效应。程序的远程部分可能会影响您的代码。

您假设它应该等待子任务,但没有做出此类假设的基础。从MSDN:

Task.WaitAll:等待所有提供的任务对象完成 执行


它完全按照它说的做。
ContinueWith
不会改变原始任务的长度,也不会变长。它将在之后立即执行。

您还需要等待继续:

Task t2 = t.ContinueWith( /* .. */ );
Task.WaitAll(new [] { t, t2 } );

即使我将“TaskContinuationOptions.AttachedToParent”与子任务的选项一起使用,也会产生相同的结果。@nunu除了将所有要等待的任务传递给WaitAll之外,没有其他解决方案,这就是复制的原因。在这个问题上所写的东西没有任何补充。没有
WaitAllAndChildren
方法。我认为您只是误解了代码的作用:
Task.Wait
正在等待主任务结束。当它结束时,它在主线程上继续执行(这样写“第三行”),主任务同时也运行继续任务(这样写“第二行”)。除非您以某种方式等待第二个(子)任务,否则不能保证最后两个任务的顺序。“不知何故”表示
Task.Wait
它也应该等待这个子任务。没有其他方法。简单地说,附加的任务只表明状态和异常应该在父任务和子任务之间“共享”。。。它不会“扩展您的原始任务而不创建另一个任务”(此外,您没有在示例代码上使用
AttachedToParent
),您应该阅读并尝试理解这一点:(第一次阅读并不容易,但要做实验)谢谢@usr!现在的问题是,我该如何等待嵌套任务完成?将该任务存储在某个位置并等待它。谢谢@Jcl!但是,我不想创建多个任务。我想用一个任务来处理这个问题。当然,我们可以将一个父任务中的嵌套任务创建为子任务,但不是完全不同的任务。您正在使用
ContinueWith
,因此您已经在创建第二个任务。。。您只是没有使用函数存储
continuew的结果,但这并不意味着没有创建任务。