繁体   English   中英

CancellationToken 不工作零超时

[英]CancellationToken not working with zero timeout

我有一个代码,它依赖于一个零超时的取消令牌来提前退出。 这是片段

using System;
using System.Threading;

namespace ConsoleApp2
{
    class Program
    {
        void DoIdleWait(TimeSpan timeout, CancellationToken cancellationToken)
        {
            var linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
            linkedCancellationTokenSource.CancelAfter(timeout);

            while (!linkedCancellationTokenSource.IsCancellationRequested)
            {
                Console.WriteLine("Waiting");
            }
        }

        static void Main(string[] args)
        {
            var prog = new Program();
            var cts = new CancellationTokenSource();
            cts.CancelAfter(TimeSpan.FromSeconds(2));
            prog.DoIdleWait(TimeSpan.Zero, cts.Token);
        }
    }
}

由于超时为零,我希望它不会进入 if 块,但它没有这样做。 知道为什么会这样吗? 另外,有什么方法可以实现我想要做的事情吗?

解释一下这个问题,

为什么,当您从具有注册超时CancellationTokenSource创建链接的CancellationTokenSource ,然后将结果令牌源设置为零超时时,它不知道应该取消吗?

更多释义

毕竟,零是零,它应该知道它被取消了......

答案是,因为CancellationTokenSource.CancelAfter尝试注册计时器回调,该回调尝试将分辨率设置为零毫秒,它不可能兑现..

因此,反过来,您将获得任何标准计时机制可以在不使用 CPU 旋转的情况下为您提供的最小分辨率,大约为 5+ 毫秒...

您的问题可能还有其他解决方案,但是,简而言之,您不能依靠0秒超时通过IsCancellationRequested立即确认。 你需要重新考虑你的问题。

CancellationTokenSource.CancelAfter方法( 源代码)不包括对TimeSpan.Zero值的特殊处理,因此将取消调度到具有零超时的TimerThreadPool 这会导致竞争条件,同步while (!linkedCancellationTokenSource.IsCancellationRequested)循环在大多数情况下获胜。 考虑到DoIdleWait方法的实现不在您的控制之下,我能想到的唯一解决方案是,如果您知道超时为零,则不要调用此方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM