type
status
date
slug
summary
tags
category
icon
password
Property
Sep 7, 2023 11:56 AM

Coninuation

一个Coninuation会对Task说:“当你结束的时候,继续再做点其他的事”
Coninuation通常是通过回调的方式实现的
  • 当操作一结束,就开始执行

例子(prime)

在task上调用GetAwaiter会返回一个阿waiter对象
  • 它的onCompleted方法会告诉之前的task:“当你结束/发生故障的时候要执行委托”
可以将Continuation附加到已经结束的task上面,此时Continuation将会被安排立即执行。

awaiter

任何可以暴露下列两个方法和一个属性的对象就是awaiter
  • OnCompleted
  • GetResult
  • 一个叫做IsCompleted的bool属性
没有接口或者父类来统一这些成员
其中OnCompleted是INotifyCompletion的一部分

如果发生故障

如果之前的任务发生故障,那么当Continuation代码调用awaiter.GetResult()的时候,异常会被重新抛出
无需调用GetResult,我们可以直接访问task的Result属性
但是调用GetResult的好处是,如果task发生故障,那么异常会被直接的抛出,而不是包裹在AggregateException里面,这样的话catch块就简洁多了

非泛型task

针对非泛型的task,GetResult()方法有一个void的返回值,他就是用来重新抛出异常的

同步上下文

如果同步上下文出现了,那么OnCompleted会自动捕获它。并将Continuation提交到这个的上下文中。这一点在富客户端非常有用,因为他会把Continuation放回到UI线程中。
如果是编写一个库,则不希望上述的行为出现,因为开销较大的UI线程切换应该在程序运行离开库的时候只发生一次,而不是出现在方法调用之间。所以,我们使用ConfigureAwait方法来避免这种行为
如果没有同步上下文出现,或者你使用的是ConfigureAwait(false),那么Continuation会运行在前task的同一个线程上,从而避免不惜要的开销

ContinueWith

另外一种附加Continuation的方式就是调用task的ContinueWith方法
ContinueWith本身返回一个task,他可以用来附加更多的Continuation
但是,必须直接处理AggregateException
  • 如果task发生故障,需要写额外的代码来把Continuation封装(marshal)到UI应用上
  • 在非UI上下文中,若想让Continuation和task执行在同一个线程上,必须制定TaskContinuationOptions.ExecuteSynchronously,否则它将弹回线程池
Continuation对于并行编程来说非常有用
C#异步编程-14 Task 的异常C#异步编程-01 线程 Thread 创建线程
  • Waline
Kitety
Kitety
独特为佳
公告
我曾经七次鄙视自己的灵魂
--卡里·纪伯伦
第一次,当它本可进取时,却故作谦卑;
第二次,当它在空虚时,用爱欲来填充;
第三次,在困难和容易之间,它选择了容易;
第四次,它犯了错,却借由别人也会犯错来宽慰自己;
第五次,它自由软弱,却把它认为是生命的坚韧;
第六次,当它鄙夷一张丑恶的嘴脸时,却不知那正是自己面具中的一副;
第七次,它侧身于生活的污泥中,虽不甘心,却又畏首畏尾。
 
最新评论
Loading...