我最近看到一些建议,指出永远不应在生产代码中使用Thread.Sleep
(最近在this SO question中)。其中许多人主张使用Task.Delay
代替。我发现的大多数解释都使用UI应用程序作为示例,因为Task.Delay
的优点是显而易见的(不会阻止UI)。
就我而言,我在等待循环中使用Thread.Sleep
来轮询WCF服务以获取特定条件,如下所示:
DateTime end = DateTime.UtcNow + TimeSpan.FromMinutes(2);
while (DateTime.UtcNow < end)
{
if (ExternalServiceIsReady() == true)
{
return true;
}
Thread.Sleep(1000);
}
在这种情况下,Task.Delay
的以下潜在优势似乎不适用:
Task.Delay
的准确度增加似乎微不足道。await
没有优势。这是否适合使用Thread.Sleep
?用Task.Delay(1000).Wait()
替换我的睡眠线会有什么好处(如果有的话)?
答案 0 :(得分:7)
替换Thread.Sleep(1000);
中的Task.Delay(1000).Wait();
绝非易事。如果您想要同步等待,请使用Thread.Sleep
。
如果您真的只有一个线程并计划保持这种方式,那么您可以使用Thread.Sleep
。但是,在大多数情况下,我仍然会使用Task.Delay
,因此这是一个很好的模式。当你不能再使用async
时,我只会阻止在顶部,即便如此,我建议使用某种AsyncContext
。
您也可以直接使用System.Threading.Timer
* 而不是Task.Delay
但是请记住,计时器会执行每个间隔而不会等待实际操作要完成,所以如果ExternalServiceIsReady
占用的时间超过间隔,则可以同时多次调用该服务。
更好的解决方案是使用异步操作替换外部服务的轮询,以便服务可以在准备就绪时通知您,而不是每秒都要求它(这并不总是可能,因为它取决于服务):
await ExternalServiceIsReadyAsync();
* Task.Delay
内部使用System.Threading.Timer
,其分辨率约为15毫秒。