• C# Task任务取消


    需求:

    在使用Blazor开发工具时,有个需求:
    扫码登录页面需要不断轮询接口获取扫码状态,并在对应的状态下进行对应的操作:刷新、登录、跳转等;
    此时,为了不阻塞前端的响应,需要我们开启一个线程进行状态检测,并在完成后结束线程任务;

    方案:

    使用取消令牌(CancellationTokenSource);
    相对操作比较简单,需要结束时调用Cancel(),同时,在Task内部进行IsCancellationRequested状态监听、或者使用暴力调用ThrowIfCancellationRequested()(同样需要不间断的调用,Cancel后才可触发,本质上也是校验IsCancellationRequested状态);

    var cts = new CancellationTokenSource();
    var tk = cts.Token;
    
    // 将CancellationToken传入action中,然后对其取消状态进行跟踪
    _ = Task.Factory.StartNew(async tk =>
    {
        CancellationToken ct = (CancellationToken)tk;
        while (true)
        {
            ct.ThrowIfCancellationRequested();
            Console.WriteLine("循环中" + Thread.CurrentThread.ManagedThreadId);
            await Task.Delay(1000);
        }
    }, tk, TaskCreationOptions.LongRunning);
    
    // OR
    
    // 此处是对于取消注册个回调方法,在取消后进行调用
    _ = Task.Factory.StartNew(async tk =>
    {
        var state = true;
        CancellationToken ct = (CancellationToken)tk;
        ct.Register(() => 
        {
            state = false;
        });
        while (state)
        {
            Console.WriteLine("循环中" + Thread.CurrentThread.ManagedThreadId);
            await Task.Delay(1000);
        }
    
    }, tk, TaskCreationOptions.LongRunning);
    

    注意:

    • 在使用Task.Run() 或 Task.Factory.StartNew()时,有个参数为传入CancellationToken,如:Run(Action, CancellationToken);该cancellationToken不会传递到Task内,更不会对Task内不造成影响,该cancellationToken 只是用于取消Run() 或 StartNew();
    • ck.Register可进行多次,构成链表执行,链表为倒叙的(最先注册的最后执行);

    扩展

    CancellationTokenSource 具体实现源码解析:浅谈C#取消令牌CancellationTokenSource
    相关项目:WeComLoad Demo

  • 相关阅读:
    记录日常Linux常用软件
    CentOS7.2重置root密码的处理方法
    Nginx配置文件详细说明
    ES项目实战
    foreachRDD
    Hive的数据倾斜
    SparkStreaming实战(数据库(NoSQL))
    Spark(4)
    SparkStreming中 `transform()`算子的 的使用
    RDD源码分析
  • 原文地址:https://www.cnblogs.com/memoyu/p/16125349.html
Copyright © 2020-2023  润新知