使用CancellationToken——而不是Thread.Sleep

目录

介绍

使用代码

兴趣点


经常发现需要在代码执行中添加暂停,乍一看远程目标或文件可能尚未准备好,所以您退后一段时间再试一次,重复执行直到目标准备好或过程被取消。在这种情况下,很容易放入Thread.Sleepn)——但这不会响应取消触发器,所以为什么不使用CancellationToken呢?

介绍

不久前,我被要求查看一项服务,该服务间歇性地在停止和关闭操作上生成异常。

该服务本身是一个简单的设备管理组件,它使用一个任务在启动时连接到远程设备,进行一些更新,仅此而已。但是,当尝试进行连接时,目标设备并不总是准备就绪,因此使用了while循环,并以调用Thread.Sleep(20000)的形式插入了暂停。

在再次尝试之前将任务暂停20秒的想法很合理——但是20秒线程块会间歇性地(取决于时间)导致服务管理器由于触发关闭或停止超时而强制关闭服务,由此产生的异常将填满日志。

Thread.Sleep(n)无法取消——请考虑使用CancellationToken.WaitHandle.WaitOne(n)

使用代码

本技巧中的代码是Thread.SleepCancellationToken.WaitHandle.WaitOne在任务中的行为的一个小示例,您可以对其进行试验

服务中实现的原始while循环如下所示:

while (!cancellationToken.IsCancellationRequested)
{
    // Processing
    if(connectionReady)
    {
        // Do its business
        break;
    }
    // Pause for 20 seconds before trying again
    Thread.Sleep(20000);
}

在此实现中,线程将被阻塞20秒——不管是否有任何取消触发器。这是潜在的问题——根据与Thread.Sleep调用有关的停止操作的时间,服务管理器将使停止操作超时并强行终止管理服务。

暂停执行代码,但知道取消请求很简单:

while (!cancellationToken.IsCancellationRequested) 
{ 
    // Processing
    if(connectionReady)
    {
        // Do its business
        break;
    }
    // Pause for 20 seconds before trying again - now with cancellation support
    var cancellationTriggered = cancellationToken.WaitHandle.WaitOne(20000);
}

这一行更改实现了与原始实现相同的20秒暂停,并且它也知道任务取消。

兴趣点

如果您发现到处都在使用Thread.Sleep(n),请考虑改为使用CancellationToken.WaitHandle.WaitOne(n)方法。这将有助于保持异常记录的大小。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值