等待已取消的任务完成,然后再继续执行

欧文·梅耶(Erwin Mayer)

我有以下代码,其中aTask可以取消,但是我基本上需要等待它完成(以确保完整性),然后再将其抛出OperationCanceledException给调用者。

public static void TaskCancellationTest() {
    try {
        Console.WriteLine("TaskCancellationTest started.");
        var cts = new CancellationTokenSource();
        var t = Task.Run(() => {
            if (cts.Token.IsCancellationRequested) return;
            Console.WriteLine("1");
            Task.Delay(2000).Wait();
            Console.WriteLine("2");
        }).ContinueWith(task => {
            if (cts.Token.IsCancellationRequested) return;
            Console.WriteLine("3");
            Task.Delay(2000).Wait();
            Console.WriteLine("4");
        });
        Task.Run(() => {
            Task.Delay(1000).Wait();
            Console.WriteLine("Cancelling...");
            cts.Cancel();
        });
        t.Wait();
        try {
            cts.Token.ThrowIfCancellationRequested();
        }
        catch (OperationCanceledException) {
            Console.WriteLine("Gracefully canceled.");
        }
        Console.WriteLine("TaskCancellationTest completed.");
    }
    catch (Exception ex) {
        Console.WriteLine("TaskCancellationTest... Failure: " + ex);
    }
}

预期的结果是:

1
Cancelling...
2
Gracefully canceled.

它可以工作,但是我更愿意将传递CancellationToken给方法,因为我知道这是一个更好的模式。我还希望能够观察方法体内的标记并调用ThrowIfCancellationRequested()中止,而不必等待next ContinueWith()。

我正在使用下面的替代代码,该代码也有效,但是有什么办法可以OperationCanceledException引发而不是AggregateException

如果我将CancellationToken传递给该WaitAll()方法,则问题在于,它将OperationCanceledException在取消令牌后立即抛出该异常,而不是等待任务t1t2实际完成(它们将继续在后台运行),然后仅引发异常。

public static void TaskCancellationTest2() {
    try {
        Console.WriteLine("TaskCancellationTest2 started.");
        var cts = new CancellationTokenSource();
        var t1 = Task.Run(() => {
            Console.WriteLine("1");
            Task.Delay(2000).Wait();
            Console.WriteLine("2");
        }, cts.Token);
        var t2 = t1.ContinueWith(task => {
            Console.WriteLine("3");
            Task.Delay(2000).Wait();
            cts.Token.ThrowIfCancellationRequested();
            Console.WriteLine("4");
        }, cts.Token);
        Task.Run(() => {
            Task.Delay(1000).Wait();
            Console.WriteLine("Cancelling...");
            cts.Cancel();
        });
        try {
            try {
                Task.WaitAll(t1, t2);
            }
            catch (AggregateException ae) {
                if (ae.InnerExceptions.Count == 1 && ae.InnerExceptions.Single() is OperationCanceledException) {
                    throw ae.InnerExceptions.Single();
                }
                throw;
            }
        }
        catch (OperationCanceledException) {
            Console.WriteLine("Gracefully canceled.");
        }
        Console.WriteLine("TaskCancellationTest2 completed.");
    }
    catch (Exception ex) {
        Console.WriteLine("TaskCancellationTest2... Failure: " + ex);
    }
}

在这里准备了一个小提琴

这个问题的标题与我的非常相似,但是很遗憾,所接受的答案与我的情况无关。

您是否知道有什么方法可以充分利用我想要的东西CancellationToken

内迪·意大利面

我认为,如果CancellationToken设置了TPL,则TPL旨在急于完成任务您看到此行为的部分原因是因为您在打电话t.Wait(cts.Token)CancellationToken即使设置了令牌,即使任务尚未完成,带a的重载也会停止等待。

这是用相同的ContinueWith,如果你传递一个CancellationToken任务能尽快为标记设置完成。

将您的代码更改为可以调用t.Wait()ContinueWith没有令牌的代码,您将获得所需的行为。

    public static void TaskCancellationTestNotWorking1()
    {
        try
        {
            Console.WriteLine("TaskCancellationTestNotWorking started.");
            var cts = new CancellationTokenSource();
            var t = Task.Run(() =>
            {
                Console.WriteLine("1");
                Thread.Sleep(2000);
                Console.WriteLine("2");
            }, cts.Token).ContinueWith(task =>
            {
                Console.WriteLine("3");
                Thread.Sleep(2000);
                cts.Token.ThrowIfCancellationRequested();
                Console.WriteLine("4");
            });

            Task.Run(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("Cancelling...");
                cts.Cancel();
            }, cts.Token);

            try
            {
                t.Wait();
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("IsCanceled " + t.IsCanceled);
                Console.WriteLine("IsCompleted " + t.IsCompleted);                    

                Console.WriteLine("Gracefully canceled.");
            }
            catch (AggregateException)
            {
                Console.WriteLine("IsCanceled " + t.IsCanceled);
                Console.WriteLine("IsCompleted " + t.IsCompleted);

                Console.WriteLine("Gracefully canceled 1.");
            }

            Console.WriteLine("TaskCancellationTestNotWorking completed.");
        }
        catch (Exception ex)
        {
            Console.WriteLine("TaskCancellationTestNotWorking... Failure: " + ex);
        }
    }

您可能会觉得这篇文章很有用。如何取消不可取消的异步操作?

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Node.js,等待所有Redis查询完成,然后再继续执行

来自分类Dev

Node.js,等待所有Redis查询完成,然后再继续执行

来自分类Dev

等待之前的块完成处理,然后再继续

来自分类Dev

等待Swift动画完成,然后再执行代码

来自分类Dev

等待任务完成,然后再次运行

来自分类Dev

等待inject.js完全执行,然后再继续执行popup.js

来自分类Dev

父进程等待所有子进程完成,然后再继续

来自分类Dev

如何使循环等待db promise完成,然后再继续下一次迭代?

来自分类Dev

SQL Server 存储过程:等待删除的触发器完成,然后再继续该过程

来自分类Dev

等待完成,然后再执行下一步

来自分类Dev

等待.sh脚本完成,然后再执行另一个.sh脚本?

来自分类Dev

等待直到线程完成,然后再执行下一步

来自分类Dev

jQuery等待函数完成,然后再执行新操作

来自分类Dev

等待循环完成,然后再执行下一个功能

来自分类Dev

等待请求完成,然后再执行下一个操作

来自分类Dev

等待GPS定位,然后再继续Android

来自分类Dev

更新您的UI并强制等待,然后再继续JavaFX

来自分类Dev

等待两个异步完成函数完成,然后再执行下一行代码

来自分类Dev

等待两个异步完成函数完成,然后再执行下一行代码

来自分类Dev

等待承诺完成,然后再处理结果

来自分类Dev

等待Ajax功能完成,然后再开始新的功能

来自分类Dev

等待thunk完成HTTP请求,然后再检查状态

来自分类Dev

等待Ajax功能完成,然后再开始新的功能

来自分类Dev

等待网络通话完成,然后再返回值

来自分类Dev

我怎样才能等到十个任务完成,然后再执行下十个任务

来自分类Dev

我怎样才能等到十个任务完成,然后再执行下十个任务

来自分类Dev

等待http.request响应,然后再执行

来自分类Dev

Android-等待线程执行,然后再启动服务

来自分类Dev

等待while循环结束,然后再执行代码

Related 相关文章

  1. 1

    Node.js,等待所有Redis查询完成,然后再继续执行

  2. 2

    Node.js,等待所有Redis查询完成,然后再继续执行

  3. 3

    等待之前的块完成处理,然后再继续

  4. 4

    等待Swift动画完成,然后再执行代码

  5. 5

    等待任务完成,然后再次运行

  6. 6

    等待inject.js完全执行,然后再继续执行popup.js

  7. 7

    父进程等待所有子进程完成,然后再继续

  8. 8

    如何使循环等待db promise完成,然后再继续下一次迭代?

  9. 9

    SQL Server 存储过程:等待删除的触发器完成,然后再继续该过程

  10. 10

    等待完成,然后再执行下一步

  11. 11

    等待.sh脚本完成,然后再执行另一个.sh脚本?

  12. 12

    等待直到线程完成,然后再执行下一步

  13. 13

    jQuery等待函数完成,然后再执行新操作

  14. 14

    等待循环完成,然后再执行下一个功能

  15. 15

    等待请求完成,然后再执行下一个操作

  16. 16

    等待GPS定位,然后再继续Android

  17. 17

    更新您的UI并强制等待,然后再继续JavaFX

  18. 18

    等待两个异步完成函数完成,然后再执行下一行代码

  19. 19

    等待两个异步完成函数完成,然后再执行下一行代码

  20. 20

    等待承诺完成,然后再处理结果

  21. 21

    等待Ajax功能完成,然后再开始新的功能

  22. 22

    等待thunk完成HTTP请求,然后再检查状态

  23. 23

    等待Ajax功能完成,然后再开始新的功能

  24. 24

    等待网络通话完成,然后再返回值

  25. 25

    我怎样才能等到十个任务完成,然后再执行下十个任务

  26. 26

    我怎样才能等到十个任务完成,然后再执行下十个任务

  27. 27

    等待http.request响应,然后再执行

  28. 28

    Android-等待线程执行,然后再启动服务

  29. 29

    等待while循环结束,然后再执行代码

热门标签

归档