Hen*_*nke 5 .net c# task-parallel-library async-await c#-5.0
当我使用该Task.WhenAll()函数并在Task中抛出异常时抛出新的AggregateException,我可以捕获它以查看Tasks中发生的所有异常.但是,当我使用时Task.WhenAny()没有抛出任何异常.相反,我必须检查Task.Exception属性值以查看是否发生了异常.这似乎是一个糟糕的代码味道,因为我必须记住Task.Exception每次使用时检查属性Task.WhenAny().难道不应该有更好的方法吗?
这是我的意思的一个例子:
private async void btnMultipleExceptions_Click(object sender, EventArgs e) {
var task1 = ThrowNotImplementedException();
var task2 = ThrowDivideByZeroException();
try {
Task task = await Task.WhenAny(task1, task2);
// Even if an exception is thrown in one of the tasks (in our case,
// task1 will throw first) no exception is thrown from
// the above await Task.WhenAny(). Instead, the exception is placed on the
// Task.Exception property. So I need to check for it every time
// I call Task.WhenAny()?
if (task.Exception != null) {
Console.WriteLine("Exceptions: " + string.Join(Environment.NewLine,
task.Exception.InnerExceptions.Select(x => x.Message).ToArray()));
} else {
Console.WriteLine("No Exceptions!");
}
} catch(Exception ex) {
// Try to catch all exceptions???
AggregateException allEx = ex as AggregateException;
if (allEx != null) {
Console.WriteLine("Exceptions: " + string.Join(Environment.NewLine,
allEx.InnerExceptions.Select(x => x.Message).ToArray()));
} else {
Console.WriteLine("Exceptions: " + ex.Message);
}
}
}
private async Task ThrowNotImplementedException() {
await Task.Delay(TimeSpan.FromSeconds(1));
throw new NotImplementedException();
}
private async Task ThrowDivideByZeroException() {
await Task.Delay(TimeSpan.FromSeconds(2));
throw new DivideByZeroException();
}
Run Code Online (Sandbox Code Playgroud)
只是await从返回的任务WhenAny。如果出错,它会解开异常并抛出它,如果没有,你知道它已经完成了,所以你可以继续。
或者,您也可以简单地拨打电话Unwrap,Task.WhenAny然后就await可以了。这在语义上与之前的选项相同;唯一的区别在于你认为这或多或少是清楚的。
如果您发现自己非常频繁地解开结果,WhenAny您可以简单地编写自己的实现来为您解开任务,并使用这些实现:
public static Task WhenAny(IEnumerable<Task> tasks)
{
return Task.WhenAny(tasks).Unwrap();
}
public static Task<T> WhenAny<T>(IEnumerable<Task<T>> tasks)
{
return Task.WhenAny(tasks).Unwrap();
}
//TODO add wrappers for the `params` overloads if you want them too
Run Code Online (Sandbox Code Playgroud)