![](/img/trans.png)
[英]How to handle the exception thrown by the async method with observable?
[英]How do I handle the messy exception that is thrown by an async method?
异步方法的异常处理有点奇怪。
如果我写一个同步方法,那就很清楚了。 例如,如果我这样做:
public static void Test1()
{
ThrowException("Test1 has a problem");
}
public static void ThrowException(string message)
{
throw new MyException(message.ToUpper());
}
我得到一个相对容易阅读的异常:
MyException thrown. Message: TEST1 HAS A PROBLEM
Trace: at Program.ThrowException(String message)
at Program.Test1()
at Program.Main()
但是,如果我做一些非常类似的事情,却是异步的:
public static async Task Test2()
{
await ThrowExceptionAsync("Test2 has a problem");
}
public static async Task ThrowExceptionAsync(string message)
{
throw new MyException(message.ToUpper());
}
我得到这个烂摊子:
System.AggregateException thrown. Message: One or more errors occurred.
Trace: at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait()
at Program.Main()
MyException thrown. Message: TEST2 HAS A PROBLEM
Trace: at Program.<ThrowExceptionAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Program.<Test2>d__1.MoveNext()
MyException thrown. Message: TEST2 HAS A PROBLEM
Trace: at Program.<ThrowExceptionAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Program.<Test2>d__1.MoveNext()
这带来了两个问题:
我无法为MyException
编写catch
块,因为它被包裹在AggregateException中。 换句话说,以下操作无效:
try { Test2().Wait(); } catch (MyException me) { //This never fires } catch(System.AggregateException e) { //It'll go here instead }
有标准的处理方法吗? 我有点想让异常更容易阅读,并且我真的很希望能够捕获MyException
而不是捕获AggregateException
并进行搜索。
您有两种选择:
await
。 如果您使用的是ASP.NET,几乎没有理由在整个堆栈中不使用async
/ await
。 .GetAwaiter().GetResult()
。 它将获得与.Result
相同的值,但还将解开异常。 await
与asynch
方法一起使用:它将解压缩异常,使您免于死锁和低效的代码。 死锁脱离主题: async
方法捕获当前的同步上下文,因此,如果尝试在同一同步上下文中等待完成,则会出现死锁。
public partial class Form1 : Form
{
public Form1() => InitializeComponent();
private void button1_Click(object sender, EventArgs e)
=> doSomthing().Wait();
private async Task doSomthing() => await Task.Delay(1000);
}
要不捕获上下文,可以使用ConfigureAwait
:
private void button1_Click(object sender, EventArgs e)
=> doSomthing()
.ConfigureAwait(continueOnCapturedContext: false)
.GetAwaiter()
.GetResult();
private async Task doSomthing() => await Task.Delay(1000);
本文深入讨论了该主题,如果您对asynch
/ await
的陷阱感兴趣,请随时阅读。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.