![](/img/trans.png)
[英]What would be a use case for Thread.Sleep(Timeout.Infinite)?
[英]Is Thread.Sleep(Timeout.Infinite); more efficient than while(true){}?
我有一个控制台应用程序,我想在监听事件的同时一直保持打开状态。 我已经测试过Thread.Sleep(Timeout.Infinite);
和while (true) { }
两者都允许在保持控制台应用程序打开的同时引发事件。 有没有我应该使用的? 如果线程正在休眠,是否有什么我不应该做的事情,例如修改在类范围内声明的静态集合?
我建议使用ManualResetEvent
(或其他WaitHandle
),并调用ManualResetEvent.WaitOne 。
这将具有与永远休眠类似的效果,但它为您提供了一种在需要时退出无限“块”的干净方法(通过在事件上调用Set()
)。
使用while(true)
会消耗 CPU 周期,因此绝对需要避免。
有什么我不应该做的事情,例如修改在类范围内声明的静态集合?
一般来说,没有。 由于您的线程将被阻塞,因此使用共享数据不应该有任何同步问题(前提是集合中的项目没有特定要求,例如必须在具有适当同步上下文的线程上使用的用户界面元素.)
从C# 7.1 开始,您可以使Main方法异步。 这意味着您可以将Main方法作为Task异步挂起,而不是使用忙等待或线程锁定睡眠。 这样,运行Main的线程就不会被锁定。 使用Cts.Cancel()
,您可以轻松释放主任务以退出应用程序(不允许其他线程/任务完成工作)。
static readonly CancellationTokenSource Cts = new CancellationTokenSource();
static async Task Main(string[] args)
{
/* your code here */
// Task running Main is efficiently suspended (no CPU use) forever until Cts activated with Program.Cts.Cancel(); (thread-safe) from anywhere.
await Task.Delay(Timeout.Infinite, Cts.Token).ConfigureAwait(false);
}
从2020 年 C# 9.0 开始,整个Program.cs
文件内容实际上看起来就像这样:
using System.Threading;
using System.Threading.Tasks;
CancellationTokenSource Cts = new();
/* your code here */
// Task running Main is efficiently suspended (no CPU use) forever until
// Cts activated with Program.Cts.Cancel(); (thread-safe) from anywhere.
await Task.Delay(Timeout.Infinite, Cts.Token).ConfigureAwait(false);
如果无限睡眠取消是这种情况的正常代码流,您可以尝试捕获 TaskCanceledException(请不要使用Task.Delay
inf-sleep那么您正在尝试等待/与其他任务同步,try-catch 效率较低并且会混淆队友):
try
{
await Task.Delay(Timeout.Infinite, Cts.Token).ConfigureAwait(false);
}
catch(TaskCanceledException) { /* Ignored */ }
我认为电话
while (true) { ... }
是计算密集型的,因为线程永远不会停止,所以
Thread.Sleep(Timeout.Infinite);
实际上在操作系统本机调度程序的帮助下让线程进入睡眠状态。 然后线程实际上停止了,所以我认为它的计算要求较低。
与while(true)...
, Thread.Sleep
不使用 CPU 周期,因此从这个意义上讲,睡眠更有效。 通常,强烈建议不要在自旋锁之外使用Busy Waiting 。
如果线程正在休眠,有什么我不应该做的吗?
由于您的线程在进入Thread.Sleep
时被阻塞,因此您希望对其资源执行的任何操作都是公平的。
是的, while(true)
消耗 CPU 而sleep()
以更智能的方式工作: sleep()
函数将当前执行上下文置于睡眠状态; 它通过调用系统调用以原子方式调用内核睡眠函数来实现这一点
(a) 设置唤醒定时器
(b) 将当前进程标记为休眠
(c) 等待直到唤醒定时器触发或中断发生
如果您调用sleep()
,CPU 可以做其他工作。
这就是sleep()
有用的原因之一。
一个有用的链接 - 使用 Sleep 时要小心
调用 Thread.Sleep 方法会导致当前线程在传递给该方法的毫秒数或时间间隔内立即阻塞,并将其时间片的剩余部分交给另一个线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.