天天看点

【异步编程】Part3:取消异步操作

在.Net和C#中运行异步代码相当简单,因为我们有时候需要取消正在进行的异步操作,通过本文,可以掌握 通过CancellationToken取消任务(包括non-cancellable任务)。

Task 表示无返回值的异步操作, 泛型版本Task<TResult>表示有返回值的异步操作, 现在async/await 语法糖大大简化了我们编写异步程序的难度。

创建一个长时间运行的操作:

【异步编程】Part3:取消异步操作
【异步编程】Part3:取消异步操作

View Code

 简单异步调用代码:

因为一些原因我们会取消异步操作:

操作耗时较长,堵塞了其他正常请求;

不愿意再等待执行结果了,手动取消

【异步编程】Part3:取消异步操作

其中关注

类CancellationTokenSource:给CancellationToken发出取消通知

结构体CancellationToken: 取消操作的通知。

CancellationToken结构体相当于打入在异步操作内部的楔子,随时等候CancellationTokenSource  发出的取消通知。

【异步编程】Part3:取消异步操作
【异步编程】Part3:取消异步操作

 定义异步方法时候设定 CancelletionToken参数

那么这个异步方法即是Cancellable 的异步方法

在长时间运行的操作中监测 IsCancellationRequested方法 (当前是否发生取消命令),这里我倾向去包装一个TaskCanceledException异常类(给上层方法调用者更多处理的可能性); 当然可以调用ThrowIfCancellationRequested方法抛出OperationCanceledException异常。

【异步编程】Part3:取消异步操作

 发送取消通知

操纵以上CancellationToken状态的对象是 CancellationTokenSource,这个对象是取消操作的命令发布者。

手动取消操作

有时候,部分第三方异步操作代码并不是可取消的,也就是以上长时间运行的异步操作LongRunningCancellableOperation(int loop, CancellationToken cancellationToken) 并不支持CancellationToken ,相当于不允许打入楔子。

这时我们怎样取消 这样的non-Cancellable 任务?

可考虑利用 Task.WhenAny( params tasks) 操作曲线取消:

利用TaskCompletionSource 注册异步可取消任务

等待待non-cancellable 操作和以上建立的 异步取消操作

像上面代码一样执行取消命令 :

【异步编程】Part3:取消异步操作

大多数情况下,我们不需要编写自定义可取消任务,因为我们只需要使用现有API。但要知道它是如何在幕后工作总是好的。

+ https://johnthiriet.com/cancel-asynchronous-operation-in-csharp/

+ https://stackoverflow.com/questions/4238345/asynchronously-wait-for-taskt-to-complete-with-timeout

+ https://github.com/App-vNext/Polly/wiki/Timeout

本文来自博客园,作者:{有态度的马甲},转载请注明原文链接:https://www.cnblogs.com/JulianHuang/p/10572840.html

欢迎关注我的原创技术、职场公众号, 加好友谈天说地,一起进化

【异步编程】Part3:取消异步操作