任务未按预期取消
本文关键字:取消 任务 | 更新日期: 2023-09-27 18:02:18
我们得到了以下场景:
class Program
{
static void Main(string[] args)
{
// trigger the delayed function
trigger();
// cancel the running task.
_token.Cancel();
// keep window open ;-)
Console.ReadLine();
}
private static CancellationTokenSource _token = null;
private static async void trigger()
{
_token = new CancellationTokenSource();
try
{
// run task
await Task.Run(async () =>
{
// wait time
await Task.Delay(2500);
// we should be cancelled here !!
Console.WriteLine(string.Format("IsCancellationRequested={0}", _token.Token.IsCancellationRequested));
Console.WriteLine("SHOULD NOT HAPPEN");
}, _token.Token);
}
catch (TaskCanceledException)
{
}
}
}
IMO预期的行为是任务的操作在 task . delay (2500)被处理后大部分被取消。
但是控制台显示:
IsCancellationRequested=True
SHOULD NOT HAPPEN
这感觉就像一个bug。如果您添加CancellationToken as参数到任务。延迟-函数,它将按预期工作。
那么,如果任务中的函数使用 task,该如何处理取消。延迟,那你可能不知道?. net中的取消是协作的。将令牌作为参数传递给Task.Run
只将令牌与返回的任务关联。
要实际取消任务,需要检查任务本身内部的令牌。如果希望在延迟内取消任务,则需要将令牌传递给Task.Delay
方法。否则,您只能在延迟之前或之后检查:
await Task.Run(async () =>
{
_token.Token.ThrowIfCancellationRequested();
await Task.Delay(2500, _token.Token);
_token.Token.ThrowIfCancellationRequested();
Console.WriteLine(string.Format("IsCancellationRequested={0}", _token.Token.IsCancellationRequested));
Console.WriteLine("SHOULD NOT HAPPEN");
}, _token.Token);
这是一篇不错的MSDN文章:https://msdn.microsoft.com/en-us/library/dd537607(v=vs.110).aspx
调用线程没有强制结束任务;它只发出信号要求取消。如果任务已经在运行,那么它就是由用户委托来通知请求和响应适当。如果在任务运行之前请求取消,则用户委托永远不会执行,任务对象会转换进入取消状态
正如i3arnon建议的那样,您可以在执行实际工作之前检查状态并抛出异常。代码节选自文章:
...
// Was cancellation already requested?
if (ct.IsCancellationRequested == true) {
Console.WriteLine("Task {0} was cancelled before it got started.",
taskNum);
ct.ThrowIfCancellationRequested();
}
...