首页 > 编程语言 >Simple WPF: C# Task异步任务的取消初探

Simple WPF: C# Task异步任务的取消初探

时间:2024-07-09 22:20:05浏览次数:15  
标签:Task Console Simple Token cancellationTokenSource C# 取消 WriteLine

最新内容优先发布于个人博客:小虎技术分享站,随后逐步搬运到博客园。
创作不易,如果觉得有用请在Github上为博主点亮一颗小星星吧!

C#中提供了CancellationTokenSource 来实现Task 的取消,方法就是在Task异步循环中检测任务是否被取消。最近正在学习C#的任务异步模型,因此撰文以记之。

无法被取消的任务

原本以为Task 是运行在被.NET管理的线程池上的,可以直接通过Task.Run 传入的CancellationToken 进行取消。结果剧本不是我想的那样,这样根本停不下来。因此还是需要在循环中去判断任务是否被取消。

static async Task TaskCannotCancellationAsync()
{
    CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
    CancellationToken token = cancellationTokenSource.Token;
    Task task = Task.Run(() =>
    {

        Console.WriteLine("Task Can not Cancellation Running...");
        Thread.Sleep(1000);
        Console.WriteLine("Task Can not Cancellation Running...");
        Console.WriteLine("Task Finished");

    }, cancellationTokenSource.Token);

    cancellationTokenSource.Token.Register(() => Console.WriteLine("Cancel Task."));
    cancellationTokenSource.CancelAfter(500);
    
    await task;
}

解下来介绍正确的可以被取消的异步任务写法。

基于异常的任务取消

我们在Task 的任务循环中检测Token 是否被取消。而取消之后就抛出异常,通过异常处理来中断原有的任务。

static async Task TaskCancellationAsync()
{
    CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
    CancellationToken token = cancellationTokenSource.Token;
    Task task = Task.Run(async () =>
    {

        token.ThrowIfCancellationRequested();

        bool moreToDo = true;
        while (moreToDo)
        {
            Console.WriteLine("Task Cancellation Running...");
            if (token.IsCancellationRequested)
            {
                token.ThrowIfCancellationRequested();
            }
            await Task.Delay(1000);
        }
        await Task.Delay(1000);
        Console.WriteLine("Task Finished");

    }, cancellationTokenSource.Token);

    cancellationTokenSource.Token.Register(() => Console.WriteLine("Cancel Task."));
    cancellationTokenSource.CancelAfter(500);

    try
    {
        await task;
    }
    catch (OperationCanceledException e)
    {
        Console.WriteLine($"{nameof(OperationCanceledException)} thrown with message: {e.Message}");
    }
    finally
    {
        cancellationTokenSource.Dispose();
    }
}

取消线程循环

既然我们可以这样取消一个死循环,那么博主就想试试看CancellationTokenSource 是否可以用于取消一个普通的线程。

static void ThreadProc(object? token)
{
    CancellationToken? cancellationToken = (CancellationToken?)token;
    while (!(cancellationToken?.IsCancellationRequested ?? true))
    {
        Console.WriteLine("ThreadMethod Working...");
        Thread.Sleep(100);
    }
}

static void ThreadAsync()
{
    CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
    Thread thread = new Thread(new ParameterizedThreadStart(ThreadProc));
    thread.Start(cancellationTokenSource.Token);
    cancellationTokenSource.CancelAfter(500);
}

测试后发现这么写也可以实现线程工作循环的取消。

完整的实验输出效果

gjF5PXQ3XRt8gEeg46LDMC4ONa9sX5mipc1o_jSj2do.gif

参考链接

https://cloud.tencent.com/developer/article/1895682

https://www.cnblogs.com/shanfeng1000/p/13402152.html

https://learn.microsoft.com/zh-cn/dotnet/standard/threading/cancellation-in-managed-threads

标签:Task,Console,Simple,Token,cancellationTokenSource,C#,取消,WriteLine
From: https://www.cnblogs.com/mrchip/p/18292844

相关文章

  • Anaconda 目录迁移 (Windows 10)
    迁移原因:C盘空间不够了,需要移动到其它盘符中。主要步骤:将anaconda3目录整个复制到新的路径里,然后修改环境变量PATH中包含anaconda3的路径为新的路径;如果要修复开始菜单中的快捷方式(包括图标变白),可以参考这篇博客到此为止,应该已经能正常使用anaconda环境了。但如果......
  • C++八股(二)之C++11新特性
    一、C++11有什么新特性?⭐自动类型推导(TypeInference):引入了auto关键字,允许编译器根据初始化表达式的类型自动推导变量的类型。统一的初始化语法(UniformInitializationSyntax):引入了用花括号{}进行初始化的统一语法,可以用于初始化各种类型的对象,包括基本类型、数组、......
  • C++八股(三)之虚函数
    目录一、虚函数可以是模板函数吗?⭐二、请你说说虚函数的工作机制⭐⭐⭐三、虚函数表在什么时候创建?每个对象都有一份虚函数表吗?四、请说说操作符重载?哪些操作符不能重载?⭐⭐五、什么是纯虚函数?⭐六、虚函数可以内联吗?⭐七、析构函数一般写成虚函数的原因?构造函数为什么......
  • xformers版本与其依赖pytorch版本的对应关系
    pip安装的xformers版本与其依赖pytorch版本的对应关系xformerspytorch0.0.26.post1torch==2.3.00.0.25torch==2.2.10.0.24torch==2.2.00.0.23torch==2.1.10.0.22torch==2.0.10.0.21torch==2.0.10.0.20torch==2.0.10.0.19torch==2.0.00.0.18torch==2.0.00.0.17torch==2.0.00......
  • [C++入门]基础与语法
    1.数据类型C++作为一种强类型语言,支持多种数据类型,这些数据类型用于声明变量、函数参数、返回值等。数据类型可以分为两大类:基本数据类型和复合数据类型。基本数据类型整型(IntegerTypes):包括int(基本整型)、short(短整型)、long(长整型)、longlong(超长整型)、char(字符型,虽常作为......
  • Rockchip RK3588 - Rockchip Linux SDK脚本分析
    ----------------------------------------------------------------------------------------------------------------------------开发板:ArmSoM-Sige7开发板eMMC:64GBLPDDR4:8GB显示屏:15.6英寸HDMI接口显示屏u-boot:2017.09linux:5.10-------------------------------......
  • docker 查看 某个容器
    转自:https://blog.51cto.com/u_16213309/7405862docker查看某个容器原创mob64ca12d2a3422023-09-0808:31:04 文章标签Dockerdocker客户端文章分类Docker云计算Docker相关视频讲解: 什么是容器 Docker介绍Docker查看某个容器在使用Docker时,我们经......
  • CAJViewer8.0_下载安装教程
    下载链接:https://fcnkteazjvur.feishu.cn/docx/S5efdYhazoQ35sx3CUCcEuCInTbCAJviewer是一款文档阅读器软件,是知网旗下的文献阅读器,可兼容CAJ和PDF等文件,支持多种文献格式,可以对其内容进行编辑,还能够从扫描的内容中提取文字,对于非扫描文档还可以实现文本和图像的摘录,并可以粘......
  • [NodeJS] JavaScript模块化
    JavaScript诞生于1995年,一开始只是用于编写简单的脚本。随着前端开发任务越来越复杂,JavaScript代码也越来越复杂,全局变量冲突、依赖管理混乱等问题变得十分突出,模块化成为一个必不可少的功能。模块化发展史与方案对比YUI与JQuery2006年,雅虎开源了组件库YUILibrary,使用类似......
  • JDBC连接MySql教程
    一.JDBC的概念JDBC全称JavaDatabaseConnectivity,是给Java开发的人员提供的一套进行数据库操作的工具,它提供了一种标准化的方式来连接到不同数据库的驱动程序,并且可以保证安全、跨平台和高效的数据访问。二.JDBC连接MySql的步骤(一)驱动准备在连接之前必要的就是对应版本......