nos*_*tio 9 .net c# task-parallel-library async-await
从方法抛出的异常的正常行为async Task是保持休眠状态,直到稍后观察它们,或者直到任务被垃圾收集.
我可以想到我可能想立即投掷的情况.这是一个例子:
public static async Task TestExAsync(string filename)
{
// the file is missing, but it may be there again
// when the exception gets observed 5 seconds later,
// hard to debug
if (!System.IO.File.Exists(filename))
throw new System.IO.FileNotFoundException(filename);
await Task.Delay(1000);
}
public static void Main()
{
var task = TestExAsync("filename");
try
{
Thread.Sleep(5000); // do other work
task.Wait(); // wait and observe
}
catch (AggregateException ex)
{
Console.WriteLine(new { ex.InnerException.Message, task.IsCanceled });
}
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
我可以用async void它绕过这个,它会立即抛出:
// disable the "use await" warning
#pragma warning disable 1998
public static async void ThrowNow(Exception ex)
{
throw ex;
}
#pragma warning restore 1998
public static async Task TestExAsync(string filename)
{
if (!System.IO.File.Exists(filename))
ThrowNow(new System.IO.FileNotFoundException(filename));
await Task.Delay(1000);
}
Run Code Online (Sandbox Code Playgroud)
现在我可以在现场处理这个异常,Dispatcher.UnhandledException或者AppDomain.CurrentDomain.UnhandledException至少立即引起用户注意.
这种情况还有其他选择吗?这可能是一个人为的问题吗?
如果你真的想这样做,你可以使用Jon Skeet 在他重新实现LINQ时使用的相同方法:创建一个可以抛出或调用真正的异步方法的同步方法:
public static Task TestExAsync(string filename)
{
if (!System.IO.File.Exists(filename))
throw new System.IO.FileNotFoundException(filename);
return TestExAsyncImpl(filename);
}
private static async Task TestExAsyncImpl(string filename)
{
await Task.Delay(1000);
}
Run Code Online (Sandbox Code Playgroud)
请记住,我认为假设Task返回方法不直接抛出是正常的.例如,您可以Task.WhenAll()在正常情况下使用从多个操作中获取所有异常,但是当立即抛出异常时,此方法将不起作用.