有没有正确的方法来取消异步任务?

2024-03-10

我遇到了如何正确取消异步任务的问题。

这是一些草稿。

我的入口点运行两个异步任务。第一个任务做了一些“长时间”的工作,第二个任务取消了它。

入口点:

private static void Main()
{
    var ctc = new CancellationTokenSource();

    var cancellable = ExecuteLongCancellableMethod(ctc.Token);

    var cancelationTask = Task.Run(() =>
    {
        Thread.Sleep(2000);

        Console.WriteLine("[Before cancellation]");

        ctc.Cancel();
    });

    try
    {
        Task.WaitAll(cancellable, cancelationTask);
    }
    catch (Exception e)
    {
        Console.WriteLine($"An exception occurred with type {e.GetType().Name}");
    }
}

返回可取消任务的方法:

private static Task ExecuteLongCancellableMethod(CancellationToken token)
{
    return Task.Run(() =>
    {
        token.ThrowIfCancellationRequested();

        Console.WriteLine("1st"); 
        Thread.Sleep(1000);

        Console.WriteLine("2nd");
        Thread.Sleep(1000);

        Console.WriteLine("3rd");
        Thread.Sleep(1000);

        Console.WriteLine("4th");
        Thread.Sleep(1000);

        Console.WriteLine("[Completed]");

    }, token);  
}   

我的目的是在调用取消后立即停止写入“1st”、“2nd”、“3rd”。但我得到以下结果:

1st
2nd
3rd
[Before cancellation]
4th
[Completed]

出于明显的原因,我没有收到请求取消时引发的异常。所以我尝试重写方法如下:

private static Task ExecuteLongCancellableAdvancedMethod(CancellationToken token)
{
    return Task.Run(() =>
    {
        var actions = new List<Action>
        {
            () => Console.WriteLine("1st"),
            () => Console.WriteLine("2nd"),
            () => Console.WriteLine("3rd"),
            () => Console.WriteLine("4th"),
            () => Console.WriteLine("[Completed]")
        };

        foreach (var action in actions)
        {
            token.ThrowIfCancellationRequested();

            action.Invoke();

            Thread.Sleep(1000);
        }

    }, token);
}

现在我得到了我想要的:

1st
2nd
[Before cancellation]
3rd
An exception occurred with type AggregateException

但我想创建一个 Action 委托集合并循环它并不是解决我的问题的最方便的方法。

那么正确的做法是什么呢?为什么我需要将取消标记作为第二个参数传递到 Task.Run 方法中?


The Task不会自行取消,您需要检测取消请求并彻底中止您的工作。就是这样token.ThrowIfCancellationRequested(); does.

您应该将这些检查放置在整个代码中,放置在可以完全停止执行或回滚到安全状态的位置。

在第二个示例中,您在循环的每次迭代中调用它一次,并且它工作得很好。第一个示例仅在开始时调用它一次。如果此时令牌尚未取消,任务将运行直至完成,就像您所看到的那样。

如果您将其更改为如下所示,您也会看到您期望的结果。

return Task.Run(() =>
{
    token.ThrowIfCancellationRequested();
    Console.WriteLine("1st"); 
    Thread.Sleep(1000);

    token.ThrowIfCancellationRequested();
    Console.WriteLine("2nd");
    Thread.Sleep(1000);

    token.ThrowIfCancellationRequested();
    Console.WriteLine("3rd");
    Thread.Sleep(1000);

    token.ThrowIfCancellationRequested();
    Console.WriteLine("4th");
    Thread.Sleep(1000);

    Console.WriteLine("[Completed]");

}, token); 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有没有正确的方法来取消异步任务? 的相关文章

随机推荐

  • 部分多键映射的数据结构?

    我的数据由映射到值的键组成 如下所示 Key Value 0 0 0 0 a 0 0 0 1 b 0 1 0 1 c 0 1 1 0 d 我正在寻找一种可以有效地对键执行搜索查询的数据结构 其中查询可以是完整或部分指定键 例如 0 0 0
  • 从 WP7 上的 xna 游戏启动 Internet Explorer

    我想知道是否可以从 Windows Phone 7 上运行的 XNA 游戏启动 Internet Explorer 我想将我的玩家重定向到我的网站 此致 我相信您仍然可以使用Web浏览器任务 http msdn microsoft com
  • ClojureScript 地图查找速度慢

    我有一个简单的地图 def my map 1 2 3 1 1 2 4 5 3 4 2 3 4 5 3 3 5 2 5 6 9 2 1 5 8 3 1 6 我用来执行查找的 然而 这表现得相当差 time doseq x range 500
  • Webpack 长期缓存

    Scenario 我正在尝试使用 webpack 将我的供应商脚本与我的应用程序脚本分开捆绑 尝试1 index js var require lodash console log webpack config js var path re
  • 如何在没有 Django 其余部分的情况下使用 Django 模板?

    我想在我的 Python 代码中使用 Django 模板引擎 但我没有构建基于 Django 的网站 如果没有 settings py 文件 和其他文件 并且必须设置 DJANGO SETTINGS MODULE 环境变量 如何使用它 如果
  • 如何获得 Java 软件商业许可? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我用 Java 编写了一个基于桌面的会计软件 我想放置密钥或许可证或其他类型的安全措施来防止客户端重新分发软件 我只是想知道该怎么办
  • 当对三个整数使用两次 = 运算符时,会发生什么? [复制]

    这个问题在这里已经有答案了 这是做什么的 int x 1 int y 2 int z 3 x y z 我在一些开源项目中遇到过多种此类事情 并且一直对它们感到困惑 我的意思是 运算符在三个整数上使用两次 即x y z 我需要理解这一点 谢谢
  • Visual Studio 无法在 Windows 10 上正确安装

    我将我的笔记本电脑升级到 Windows 10 无预览版 真正的东西 然后我安装了 Visual Studio Community Edition 2015 我已经安装了 VS 2013 这样我就可以开始使用 Cordova 功能 安装过程
  • 使用 p 值的逐步回归删除 p 值不显着的变量

    我想表演一个逐步线性回归 using p values作为选择标准 例如 在每个步骤中删除具有最高即最不显着 p 值的变量 当所有值均由某个阈值定义的显着时停止alpha 我完全知道我应该使用 AIC 例如命令step or stepAIC
  • 获取当前function()作用域的所有变量

    我有问题 我想获取当前的函数范围 我有这个示例代码 我工作正常 function nittle var Pen new Dot Generated dynamical through eval for key in window if wi
  • 使用 Boto3 从 S3 下载文件夹

    Using Boto3 Python SDK 我能够使用该方法下载文件bucket download file 有没有办法下载整个文件夹 Answer recommended by AWS collectives aws Collectiv
  • Python:如何使用 xlwt 编写复数到 Excel?

    我正在尝试使用以下命令将 Python 列表写入 Excel 文件xlwt图书馆 import xlwt from tempfile import TemporaryFile book xlwt Workbook sheet1 book a
  • 调用静态 JNI 方法从 C++ 返回字符串

    我正在尝试在Android中调用以下java方法 public static String getLevelFile String levelName body 从 C 使用以下 jni 代码 JniMethodInfoJavaApi me
  • 调用window.location.href后如何执行脚本?

    我有一个脚本可以将用户重定向到另一个页面 我想在新页面完全加载后将一些内容加载到新页面上的 div 中 我怎样才能做到这一点 以下不起作用 function goToPage window location href http www my
  • 如何在bash中测试变量是否以字符串开头?

    对于固定的前缀长度 我可以这样做 a filename 0 2 a echo temporary emacs file 对于任意前缀如何做到这一点 有更干净的方法吗 s 运算符在右操作数中采用模式 var 123 1234 var
  • 包设置不会传播到分布式的工作人员

    Info julia version julia version 1 6 0 lscpu root MyPackage lscpu Architecture x86 64 CPU op mode s 32 bit 64 bit Byte O
  • 图像具有绝对路径 - 如何在 Laravel Mix 中使用子目录 URL

    我的 Laravel Mix 应用程序将放置在服务器上的子目录中 例如 http localhost pat os server public http localhost pat os server public 我的 vue 组件中的图
  • C# 中 if 语句的性能 [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我只是想确定在具有大量迭代的循环中使用每个 if 语句对 C 应用程序性能的影响 我还没有找到与此相关的主题 因此我创建了这个主题 对于测试
  • 如何使用 MOQ 对象测试 Ninject ConstructorArguments?

    我最近一直在做我的第一个测试驱动开发项目 并一直在学习 Ninject 和 MOQ 这是我第一次尝试这一切 我发现 TDD 方法发人深省 Ninject 和 MOQ 也很棒 我正在从事的项目并不是特别适合 Ninject 因为它是一个高度可
  • 有没有正确的方法来取消异步任务?

    我遇到了如何正确取消异步任务的问题 这是一些草稿 我的入口点运行两个异步任务 第一个任务做了一些 长时间 的工作 第二个任务取消了它 入口点 private static void Main var ctc new Cancellation