博客
关于我
取消任务
阅读量: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/

你可能感兴趣的文章
ngModelController
查看>>
ngnix配置文件
查看>>
ngrok | 内网穿透,支持 HTTPS、国内访问、静态域名
查看>>
ngrok内网穿透可以实现资源共享吗?快解析更加简洁
查看>>
ngrok内网穿透可以实现资源共享吗?快解析更加简洁
查看>>
NHibernate动态添加表
查看>>
NHibernate学习[1]
查看>>
NHibernate异常:No persister for的解决办法
查看>>
Nhibernate的第一个实例
查看>>
NHibernate示例
查看>>
nid修改oracle11gR2数据库名
查看>>
NIFI1.21.0/NIFI1.22.0/NIFI1.24.0/NIFI1.26.0_2024-06-11最新版本安装_采用HTTP方式_搭建集群_实际操作---大数据之Nifi工作笔记0050
查看>>
NIFI1.21.0_java.net.SocketException:_Too many open files 打开的文件太多_实际操作---大数据之Nifi工作笔记0051
查看>>
NIFI1.21.0_Mysql到Mysql增量CDC同步中_日期类型_以及null数据同步处理补充---大数据之Nifi工作笔记0057
查看>>
NIFI1.21.0_Mysql到Mysql增量CDC同步中_补充_插入时如果目标表中已存在该数据则自动改为更新数据_Postgresql_Hbase也适用---大数据之Nifi工作笔记0058
查看>>
NIFI1.21.0_Mysql到Mysql增量CDC同步中_补充_更新时如果目标表中不存在记录就改为插入数据_Postgresql_Hbase也适用---大数据之Nifi工作笔记0059
查看>>
NIFI1.21.0_NIFI和hadoop蹦了_200G集群磁盘又满了_Jps看不到进程了_Unable to write in /tmp. Aborting----大数据之Nifi工作笔记0052
查看>>
NIFI1.21.0_Postgresql和Mysql同时指定库_指定多表_全量同步到Mysql数据库以及Hbase数据库中---大数据之Nifi工作笔记0060
查看>>
NIFI1.21.0最新版本安装_连接phoenix_单机版_Https登录_什么都没改换了最新版本的NIFI可以连接了_气人_实现插入数据到Hbase_实际操作---大数据之Nifi工作笔记0050
查看>>
NIFI1.21.0最新版本安装_配置使用HTTP登录_默认是用HTTPS登录的_Https登录需要输入用户名密码_HTTP不需要---大数据之Nifi工作笔记0051
查看>>