当我使用CancelAfter()时,任务仍在运行 [英] When I use CancelAfter(), the Task is still running
问题描述
我要使用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屋!