我的延续任务似乎在完成之前就已完成 运行
My continuation task appears to be complete before it finishes running
我有一个关于延续任务的非直觉问题,我认为 task.Wait 会等待延续任务,但它在任务完成之前 RanToCompletion
产生 运行ning ?这是简短的源代码。输出如下:
private static void TestChildTasks()
{
Task t = Task.Run(() => RunParentTask());
Task t2 = t.ContinueWith(task => Task.Run(() => RunChildTask()));
//Task t2 = Task.Run(() => RunChildTask());
Console.WriteLine("Waiting on t1");
t.Wait();
Console.WriteLine("Done waiting on t1");
Console.WriteLine($"Waiting on t2, status of {t2.Status}");
t2.Wait();
Console.WriteLine($"Finished; child task is {t2.Status}");
}
private static void RunParentTask()
{
Console.WriteLine("Parent Task is running");
Thread.Sleep(2000);
Console.WriteLine("Parent Task is done");
}
private static void RunChildTask()
{
Console.WriteLine("Child task is running");
Thread.Sleep(3000);
Console.WriteLine("Child Task is done");
}
这是输出:
Waiting on t1
Parent Task is running
Parent Task is done
Done waiting on t1
Waiting on t2, status of Running
Finished; child task is RanToCompletion
press enter to exit
Child task is running
Child Task is done
为什么子任务在 returns 之后继续 运行 RanToCompletion
的状态?
让我们看看下面一行:
Task t2 = t.ContinueWith(task => Task.Run(() => RunChildTask()));
尽管您已将 t2
声明为 Task
,但它实际上是 Task<Task>
:
Task<Task> t2 = t.ContinueWith(task => Task.Run(() => RunChildTask()));
为什么?因为 Task.Run
创建了一个新的 Task
.
您有多种选择可以解决此问题:
选项 #1 - 展开
要从 Task<Task>
生成 Task
,您需要调用 Unwrap
方法。
Task t2 = t.ContinueWith(task => Task.Run(() => RunChildTask())).Unwrap();
经过此修改,输出将如下所示:
Waiting on t1
Parent Task is running
Parent Task is done
Done waiting on t1
Child task is running
Waiting on t2, status of WaitingForActivation
Child Task is done
Finished; child task is RanToCompletion
选项 #2 - 避免创建新任务
实际上你可以在没有 Task.Run
的情况下调用 RunChildTask
:
Task t2 = t.ContinueWith(_ => RunChildTask());
经过此修改,输出将如下所示:
Waiting on t1
Parent Task is running
Parent Task is done
Done waiting on t1
Child task is running
Waiting on t2, status of Running
Child Task is done
Finished; child task is RanToCompletion
选项 #3 - AttachToParent
如果您愿意,您不仅可以使用 ContinueWith
附加任务,还可以使用 Task.Factory.StartNew
:
Task t2 = null;
Task t = Task.Factory.StartNew(() =>
{
RunParentTask();
t2 = Task.Factory.StartNew(RunChildTask, TaskCreationOptions.AttachedToParent);
});
经过此修改,输出将如下所示:
Waiting on t1
Parent Task is running
Parent Task is done
Child task is running
Child Task is done
Done waiting on t1
Waiting on t2, status of RanToCompletion
Finished; child task is RanToCompletion
还有其他几种方法。
我有一个关于延续任务的非直觉问题,我认为 task.Wait 会等待延续任务,但它在任务完成之前 RanToCompletion
产生 运行ning ?这是简短的源代码。输出如下:
private static void TestChildTasks()
{
Task t = Task.Run(() => RunParentTask());
Task t2 = t.ContinueWith(task => Task.Run(() => RunChildTask()));
//Task t2 = Task.Run(() => RunChildTask());
Console.WriteLine("Waiting on t1");
t.Wait();
Console.WriteLine("Done waiting on t1");
Console.WriteLine($"Waiting on t2, status of {t2.Status}");
t2.Wait();
Console.WriteLine($"Finished; child task is {t2.Status}");
}
private static void RunParentTask()
{
Console.WriteLine("Parent Task is running");
Thread.Sleep(2000);
Console.WriteLine("Parent Task is done");
}
private static void RunChildTask()
{
Console.WriteLine("Child task is running");
Thread.Sleep(3000);
Console.WriteLine("Child Task is done");
}
这是输出:
Waiting on t1
Parent Task is running
Parent Task is done
Done waiting on t1
Waiting on t2, status of Running
Finished; child task is RanToCompletion
press enter to exit
Child task is running
Child Task is done
为什么子任务在 returns 之后继续 运行 RanToCompletion
的状态?
让我们看看下面一行:
Task t2 = t.ContinueWith(task => Task.Run(() => RunChildTask()));
尽管您已将 t2
声明为 Task
,但它实际上是 Task<Task>
:
Task<Task> t2 = t.ContinueWith(task => Task.Run(() => RunChildTask()));
为什么?因为 Task.Run
创建了一个新的 Task
.
您有多种选择可以解决此问题:
选项 #1 - 展开
要从 Task<Task>
生成 Task
,您需要调用 Unwrap
方法。
Task t2 = t.ContinueWith(task => Task.Run(() => RunChildTask())).Unwrap();
经过此修改,输出将如下所示:
Waiting on t1
Parent Task is running
Parent Task is done
Done waiting on t1
Child task is running
Waiting on t2, status of WaitingForActivation
Child Task is done
Finished; child task is RanToCompletion
选项 #2 - 避免创建新任务
实际上你可以在没有 Task.Run
的情况下调用 RunChildTask
:
Task t2 = t.ContinueWith(_ => RunChildTask());
经过此修改,输出将如下所示:
Waiting on t1
Parent Task is running
Parent Task is done
Done waiting on t1
Child task is running
Waiting on t2, status of Running
Child Task is done
Finished; child task is RanToCompletion
选项 #3 - AttachToParent
如果您愿意,您不仅可以使用 ContinueWith
附加任务,还可以使用 Task.Factory.StartNew
:
Task t2 = null;
Task t = Task.Factory.StartNew(() =>
{
RunParentTask();
t2 = Task.Factory.StartNew(RunChildTask, TaskCreationOptions.AttachedToParent);
});
经过此修改,输出将如下所示:
Waiting on t1
Parent Task is running
Parent Task is done
Child task is running
Child Task is done
Done waiting on t1
Waiting on t2, status of RanToCompletion
Finished; child task is RanToCompletion
还有其他几种方法。