任务不等待ContinueWith完成

4
我有一个控制台应用程序,代码如下:
问题在于在ContinueWith任务完成之前,控制台应用程序就已经结束了,它不等待ContinueWith任务完成,请指导。
请告诉我我缺少什么或者哪里出错了。
var task1 = Task<bool>.Factory.StartNew(() => DoProcess());

task1 .ContinueWith(
     t1 => updateSuccess(),
       TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously);

task1 .ContinueWith(
     t => updateFault(),
     TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);

task1.Wait();
3个回答

8
你需要在主线程上等待任务完成。简化后如下:
var task1 = Task<bool>.Factory.StartNew(() => DoProcess());

successContinuation = task1 .ContinueWith(t1 => updateSuccess(),
                                          TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously)
failureContinuation = task1 .ContinueWith( t => updateFault(),
                                          TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);

Task.WaitAny(successContinuation, failureContinuation);

我认为你没有意识到你正在创建一个可能在不同线程中执行的任务。一旦你启动了任务,你就有了两个不同的执行线程:主线程(将继续运行)和你的任务。如果你希望主线程(即控制台应用程序)等待任务完成,你必须手动指定。


如果您查看上面的代码,它还具有根据“TaskContinuationOptions”执行或不执行的条件,因此如果其中一个continueWith执行,则其他continueWith将以任务取消错误失败。请建议如何避免这种情况。 - Keshavdas M
由于连续项是互斥的(它要么失败,要么成功,因此只有其中一个结果任务会运行),所以您需要等待它们中的任何一个完成。 - Jorge Córdoba

2

Jorge的解决方案在抛出异常时无法正常工作:

var task = new Task(() =>
    {
        Console.WriteLine("My task...");
        throw new Exception();
    });

task.Start();

var taskNotOnFaulted = task.ContinueWith(t =>
{
    Thread.Sleep(1000);
    Console.WriteLine("NotOnFaulted");
}, TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
var taskOnlyOnFaulted = task.ContinueWith(t =>
{
    Thread.Sleep(1000);
    Console.Write("OnlyOnFaulted");
}, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);

Task.WaitAny(taskNotOnFaulted, taskOnlyOnFaulted);

Console.WriteLine("Finished");

输出结果为:
My task...
Finished
OnlyOnFaulted

这是因为当抛出异常时,taskNotOnFaulted状态为Cancelled,而没有抛出异常时,状态为WaitingForActivation。所以你需要替换:

Task.WaitAny(taskNotOnFaulted, taskOnlyOnFaulted);

由谁编写的。
if (task.IsFaulted)
    taskOnlyOnFaulted.Wait();
else
    taskNotOnFaulted.Wait();

0

我尝试了另一种解决方案,对我有效:

try {
    taskNotOnFaulted.Wait();
} catch {
    taskOnlyOnFaulted.Wait();
}

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