如何观察取消令牌?

时间:2018-10-26 13:00:26

标签: c# .net

除了在循环中检查取消令牌以外,还有其他方法可以观察取消令牌吗?

while (moreToDo)
{
    // Poll on this property if you have to do
    // other cleanup before throwing.
    if (cancellationToken.IsCancellationRequested)
    {
        // Clean up here, then...
        cancellationToken.ThrowIfCancellationRequested();
     }

}

示例来自:https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/task-cancellation

当方法运行超过5秒时,我想取消任务。但是处理VeryLong方法可能需要5秒钟以上。

var cancelationTokenSource = new CancellationTokenSource(5000);
Task.Factory.StartNew(
     () =>
     {
         VeryLongMethod();

      }, cancelationTokenSource.Token
);

有人建议我尝试注册回调,但是在超时后,仍然执行了很长的方法。

var cancellationTokenSource = new CancellationTokenSource(20000);

        await Task.Factory.StartNew
        (
            () =>
            {
                using (cancellationTokenSource.Token.Register(() =>
                {

                    Program.Console.WriteToConsole("Failed on timeout.");


                    try
                    {
                        cancellationTokenSource.Token.ThrowIfCancellationRequested();
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Action was processed already");                            
                    }

                }))
                {
                    VeryLongMethod();
                }
            }, cancellationTokenSource.Token
        );

2 个答案:

答案 0 :(得分:1)

您可以注册一个回调,当令牌被取消时将被调用:

using(var reg = cancellationToken.Register(() => { /* cancellation logic */ }))
{
    // your code
}

更新:对于您更新的问题,您可以告诉取消令牌来源,一段时间后必须取消其令牌,如下所示:

cancelationTokenSource.CancelAfter(TimeSpan.FromSeconds(5));

答案 1 :(得分:0)

简而言之,不。定期池化是我们检查任务是否打算取消的唯一方法。 CancellationToken不提供任何其他通知方式来检查它,IsCancellationRequestedThrowIfCancellationRequested是我们唯一知道必须取消的方式。

这意味着在当前基于异步等待任务的设计中,可取消方法必须定期检查自身,以了解调用者是否要取消并自行提供退出点。现在,如果不将其更改为与取消系统“合作”,就没有直接取消方法的方法。

它本身不需要循环,但是无论如何,检查都需要某种形式的合并。循环是典型的构造,但可以使用其他任何东西。