有没有办法在不抛出异常的情况下等待 TPL 任务?

Is there a way to Wait for a TPL Task without in throwing an exception?

我们中的一些人更喜欢以异常轻的风格编写代码。但是,如果您等待一个 Task Parallel Library 任务,而该任务抛出异常,它也会在调用线程上抛出异常。是否有一种(最好是标准的)方法来避免这种行为,并在您取回响应时检查异常响应?

根据您所写的内容,捕获异常并检查 IsFaulted 属性 可能是您的解决方案吗? IsFaulted

在任务中捕获异常并return它在结果中?

var task1 = Task.Factory.StartNew(() =>
{
    try
    {
        throw new MyCustomException("I'm bad, but not too bad!");
    }
    catch(Exception ex)
    {
        return new Result { Error = ex };
    }
});

很遗憾,此功能不是内置的。使用此解决方法:

 myTask.ContinueWith(_ => { }, TaskContinuationOptions.ExecuteSynchronously).Wait();

你可以把它变成一个扩展方法。

您可以像这样使用Task.WaitAny:

        var task = Task.Run(() =>
        {
            // ...
            throw new Exception("Blah");
        });
        Task.WaitAny(task);
        if (task.IsFaulted)
        {
            var error = task.Exception;
            // ...
        }
        else if (task.IsCanceled)
        {
            // ...
        }
        else
        {
            // Success
        }

您不能在不引发异常的情况下等待故障任务。 但是您可以等待该任务的继续,只有在原始任务完成且不引发异常后,该任务才会完成:

public static Task SwallowExceptions(this Task task)
{
    return task.ContinueWith(_ => { });
}

faultedTask.SwallowExceptions().Wait();
if (faultedTask.IsFaulted)
{
    // handle exception
}

如果您的任务 return 是一个值,您可以在扩展方法中表示该值,并且 return 实际值(如果没有异常)或默认值(如果有):

public static Task<T> SwallowExceptions<T>(this Task<T> task)
{
    return task.ContinueWith(completedTask => 
        completedTask.IsFaulted 
            ? default(T) 
            : completedTask.Result);
}