type
status
date
slug
summary
tags
category
icon
password
Property
Aug 9, 2024 11:58 AM
发布异常
富客户端应用通常依赖于集中的异常处理事件来处理UI线程上未捕获的异常
- WPF中的Application.DispatcherUnhandledException
- ASP.NET Core中定制ExceptionFilterAttribute也是差不多的效果
其内部原理就是:通过他们自己的try catch块来调用UI事件(在ASP.NET Core里面就是页面处理方法的管道)
顶层的异步方法会使事情更加复杂
- 当点击按钮,event handler运行时,在await后,执行会正常的返回到消息循环;1秒之后抛出的异常无法被消息循环中的catch捕获
- 为了缓解该问题,AsyncVoidMethodBuilder会捕获未处理的异常(在返回void的异步方法里),并把他们发布到同步上下文(如果出现的话),以确保全局异常处理事件能够触发
注意
编译器只会把上述逻辑应用于返回值为void的异步方法
入股ButtonClick的返回类型是Task,name未处理的异常将导致Task出错,
然后Task无处可去(导致为观察到的异常)
发布异常
一个有趣的细微差别:无论你在await前面还是后面抛出异常,都没有区别
因此下列中,异常会被发布到同步上下文(如果出现的话),而不会发布给调用者
- async void Foo(){throw null; await Task.Delay(1000);}
- 如果同步上下文没有出现,异常将会在线程池传播,从而终止程序
不直接将异常抛出回调者的原因是为了确保可预测性和一致性
在下例中,不管someCondition是什么值,InvalidOperationException将始终得到和导致Task出现同样的效果
Iterrator也是一样的
本例中,异常绝不会直接返回给调用者,直到序列被遍历后,才抛出异常
OperationStarted和OperationCompleted
如果存在同步上下文,返回void的异步函数也会在进入函数时调用其OperationStarted方法,在函数完成时调用其OperationCompleted方法
如果为了对返回void的异步方法尽心单元测试而编写一个自定义的同步上下文,name重写这两个方法确实很有用
- 作者:Kitety
- 链接:https://www.kitety.com/article/c-sharp-async-context
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章