当我使用CancelAfter()时,任务仍在运行 [英] When I use CancelAfter(), the Task is still running

查看:152
本文介绍了当我使用CancelAfter()时,任务仍在运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要使用CancellationTokenSource停止任务. 我的测试如下:

I want to use CancellationTokenSource stop the Task. My tests as follow:

测试1:使用Cancel()成功停止了任务.

Test 1 : Using Cancel() stopped the task sucessfully.

测试2:使用CancelAfter()并没有停止任务,为什么?

Test 2 : Using CancelAfter() did not stop the task, Why?

任务动作是:

    static Action testFun = () => {
        Thread.Sleep(4000); // or other a long time operation
        Console.WriteLine("Action is end");
    };

test1代码:

        CancellationTokenSource source = new CancellationTokenSource(); 
        CancellationToken token = source.Token;
        //Register the cancel action
        token.Register(() =>
        {
            Console.WriteLine("Task is canceled");
        });
        Task task = new Task(testFun, token); 
        task.Start();
        source.Cancel();     
        Console.ReadLine();

输出为:

Task is canceled

Test2代码:

        CancellationTokenSource source = new CancellationTokenSource(); 
        CancellationToken token = source.Token;
        //Register the cancel action
        token.Register(() =>
        {
            Console.WriteLine("Task is canceled");
        });
        Task task = new Task(testFun, token); 
        task.Start();
        source.CancelAfter(100); // the time 100ms < the task 4000ms
        Console.ReadLine();

输出为:

Task is canceled
Action is end

我的问题是,为什么在CancellationTokenSource上调用CancelAfter()时任务仍在运行

My question is why task is still running when CancelAfter() is invoked on CancellationTokenSource

我如何修改test2?谢谢.

How do I revise the test2 ? Thank you.

推荐答案

CancelationToken有点误导.问题是,如果Task已经启动,除非您明确检查CancelationToken,例如CancellationToken.ThrowIfCancellationRequested,否则无法停止它. CancelationToken的目的是防止Task在仍被安排时启动.

The CancelationToken is kind of a misleading. The problem is that if Task is already started it cannot be stopped unless you explicitly check CancelationToken, for example CancellationToken.ThrowIfCancellationRequested. The purpose of the CancelationToken is to prevent the Task to start while it is still scheduled.

这与您的示例有所不同,使用Cancel您可以在仍按计划执行的任务中取消该任务,但是使用CancelAfter任务已经启动并且无法再停止它了.

That is difference in your example, with Cancel you cancel the task while it is still scheduled but with CancelAfter task is already started and there is no way to stop it anymore.

首先,是CancellationToken.如果您在 预定了继续,那么继续委托永远不会 实际运行-已取消.但是,请注意,令牌不 一旦开始继续,请取消继续.换句话说, CancellationToken取消继续的调度,而不是取消 延续本身.因此,我认为CancellationToken 参数会产生误导,我自己也从未使用过.

First, the CancellationToken. If you cancel the token before the continuation is scheduled, then the continuation delegate never actually runs - it’s cancelled. However, note that the token does not cancel the continuation once it has started. In other words, the CancellationToken cancels the scheduling of the continuation, not the continuation itself. For this reason, I think the CancellationToken parameter is misleading, and I never use it myself.

https://blog.stephencleary. com/2015/01/a-tour-of-task-part-7-continuations.html

解释Task延续性的部分,但与Task本身相同,延续性仍然会安排新任务.

Part explaining the continuation of the Task but it is the same also with the Task itself, continuation will schedule new task anyway.

CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;

//If cancelAfter > taskWaiting - task will be finished
//If canceAfter < taskWaiting - task will be canceled
//If cancelAfter == taskWaiting - unexpected :)
int cancelAfter = 100;
int taskWaiting = 200;          

//If token is canceled before run of the task it won't start at all
//source.Cancel();

//Register the cancel action
token.Register(() =>
{
    Console.WriteLine("Task is canceled");
});

Task.Run(() =>
{
    Console.WriteLine("Action is started");
    Thread.Sleep(taskWaiting);

    if (token.IsCancellationRequested)
        return;             

    Console.WriteLine("Action is finished");
}, token);          

source.CancelAfter(cancelAfter);

这篇关于当我使用CancelAfter()时,任务仍在运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆