type
Post
status
Published
date
Sep 21, 2023
slug
c-sharp-async-context
summary
C#异步编程-21 异步中的同步上下文
tags
C#
CS
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 许可协议,转载请注明出处。
相关文章


.png?table=block&id=fa81f9ab-c0da-4f4e-a935-0567380c36d0&t=fa81f9ab-c0da-4f4e-a935-0567380c36d0&width=1080&cache=v2)
.png?table=block&id=55df38cd-a361-41ee-a75d-c17615e78d6b&t=55df38cd-a361-41ee-a75d-c17615e78d6b&width=1080&cache=v2)
.png?table=block&id=23baa6c3-e959-44c5-a699-ce0df9ba58ee&t=23baa6c3-e959-44c5-a699-ce0df9ba58ee&width=1080&cache=v2)
_(1).jpg?table=block&id=a716c7ee-7105-4a3f-8133-a15129086419&t=a716c7ee-7105-4a3f-8133-a15129086419&width=1080&cache=v2)
.jpg?table=block&id=2e9784d9-1d6e-44fc-9106-f0c576ddcb8f&t=2e9784d9-1d6e-44fc-9106-f0c576ddcb8f&width=1080&cache=v2)

.png?table=block&id=c0772cdb-ee08-49f4-b2f3-c804586bb769&t=c0772cdb-ee08-49f4-b2f3-c804586bb769&width=1080&cache=v2)

.png?table=block&id=b43ea4ae-a57d-4962-80ba-12280979702b&t=b43ea4ae-a57d-4962-80ba-12280979702b&width=1080&cache=v2)
