博客
关于我
取消任务
阅读量:398 次
发布时间:2019-03-05

本文共 3591 字,大约阅读时间需要 11 分钟。

CancellationToken.None 是一个等同于默认的特殊值,表示这个方法是永远不会被取消的。

实例代码

static async Task CancelableMethodAsync(CancellationToken token){    await Task.Delay(1000, token);    throw new ArgumentException();}public static async Task IssueCancelRequestAsync(){    var cts = new CancellationTokenSource();    var task = CancelableMethodAsync(cts.Token);    // 这里,操作在正常运行。    // 发出取消请求。    cts.Cancel();    //(异步地)等待操作结束。    try    {        await task;        // 如运行到这里,说明在取消请求生效前,操作正常完成 。    }    catch (OperationCanceledException ex)    {        // 如运行到这里,说明操作在完成前被取消。        System.Console.WriteLine(ex.GetType().Name);    }    catch (Exception ex)    {        // 如运行到这里,说明在取消请求生效前,操作出错并结束。        System.Console.WriteLine(ex.GetType().Name);    }}

输出:

TaskCanceledException

1. 取消请求

public static int CancelableMethod(CancellationToken cancellationToken){    for (int i = 0; i != 100000; ++i)    {        // cancellationToken.WaitHandle.WaitOne(1000);        Thread.Sleep(1);        // 这里做一些计算工作。        if (i % 1000 == 0)            cancellationToken.ThrowIfCancellationRequested();    }    return 42;}

2. 超时后取消

public static async Task IssueTimeoutAsync(){    Stopwatch sw = Stopwatch.StartNew();    try    {        var cts = new CancellationTokenSource();        var token = cts.Token;        cts.CancelAfter(TimeSpan.FromSeconds(2));        await Task.Delay(TimeSpan.FromSeconds(4), token);    }    finally    {        System.Console.WriteLine($"{sw.ElapsedMilliseconds}ms");    }}

输出:

2004msUnhandled Exception: ... ...

只要执行代码时用到了超时,就该使用 CancellationTokenSourceCancelAfter (或者用构造函数)。虽然还有其他途径可实现这个功能,但是使用现有的取消体系是最简单也是最高效的。

3. 取消并行

public class Matrix{    public void Rotate(float degrees) { }}//只做展示public static void RotateMatrices(IEnumerable
matrices, float degrees, CancellationToken token){ Parallel.ForEach(matrices, new ParallelOptions { CancellationToken = token }, matrix => matrix.Rotate(degrees));}

4. 取消响应式代码

注入取消请求

  • 某一个层次的代码需要响应取消请求,同时它本身也要向下一层代码发出取消请求(但不会向上传递)。
public static async Task RunGetWithTimeoutAsync(){    CancellationTokenSource source = new CancellationTokenSource();    await GetWithTimeoutAsync("http://www.baidu.com", source.Token);}public static async Task
GetWithTimeoutAsync(string url, CancellationToken cancellationToken){ var client = new HttpClient(); using (var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)) { cts.CancelAfter(TimeSpan.FromMilliseconds(100)); var combinedToken = cts.Token; return await client.GetAsync(url, combinedToken); }}

输出:

Unhandled Exception: Unhandled exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.AggregateException: One or more errors occurred. (A task was canceled.) ---> System.Threading.Tasks.TaskCanceledException ... ...

5. 与其他取消体系的互操作

有一些外部的或以前遗留下来的代码采用了非标准的取消模式。现在要用标准的CancellationToken 来控制这些代码

public static async Task RunPingAsync(){    var cts = new CancellationTokenSource();    var task = PingAsync("192.168.0.101", cts.Token);    //cts.Cancel();    await task;}public static async Task
PingAsync(string hostNameOrAddress, CancellationToken cancellationToken){ Stopwatch sw = Stopwatch.StartNew(); try { var ping = new Ping(); using (cancellationToken.Register(() => ping.SendAsyncCancel())) { return await ping.SendPingAsync(hostNameOrAddress); } } finally { System.Console.WriteLine($"{sw.ElapsedMilliseconds}ms"); }}

注意: 为了避免内存和资源的泄漏,一旦不再需要使用回调函数了,就要释放这个回调函数注册。

转载地址:http://pbozz.baihongyu.com/

你可能感兴趣的文章
mysql源码安装
查看>>
Mysql源码安装过程中可能碰到的问题
查看>>
MySQL灵魂16问,你能撑到第几问?
查看>>
MySQL灵魂拷问:36题带你面试通关
查看>>
mysql状态分析之show global status
查看>>
mysql状态查看 QPS/TPS/缓存命中率查看
查看>>
mysql生成树形数据_mysql 实现树形的遍历
查看>>
mysql用于检索的关键字_Mysql全文搜索match...against的用法
查看>>
MySQL用得好好的,为什么要转ES?
查看>>
MySql用户以及权限的管理。
查看>>
MySQL用户权限配置:精细控制和远程访问的艺术!------文章最后有惊喜哦。
查看>>
mysql用户管理、常用语句、数据分备份恢复
查看>>
MySQL留疑问:left join时选on还是where?
查看>>
mysql登陆慢问题解决
查看>>
Mysql百万级数据查询优化
查看>>
MySQL的 DDL和DML和DQL的基本语法
查看>>
mysql的 if else , case when then, IFNULL
查看>>
MySQL的10种常用数据类型
查看>>
MySQL的btree索引和hash索引的区别
查看>>
mysql的cast函数
查看>>