C# 是Thread.Sleep(Timeout.Infinite);比while(true){}更有效?

C# 是Thread.Sleep(Timeout.Infinite);比while(true){}更有效?,c#,console-application,C#,Console Application,我有一个控制台应用程序,我希望在监听事件的同时一直保持打开状态。我已经测试了Thread.Sleep(Timeout.Infinite)和while(true){}都允许在保持控制台应用程序打开的同时引发事件。有一个我应该用在另一个上面吗?如果线程处于睡眠状态,是否有什么我不应该做的事情,例如修改类范围内声明的静态集合?与while(true)不同,线程。睡眠不使用CPU周期,因此从这个意义上讲,睡眠更有效。一般来说,强烈反对在外部使用 如果线在睡觉,有什么我不应该做的吗 由于您的线程在进入th

我有一个控制台应用程序,我希望在监听事件的同时一直保持打开状态。我已经测试了
Thread.Sleep(Timeout.Infinite)
while(true){}
都允许在保持控制台应用程序打开的同时引发事件。有一个我应该用在另一个上面吗?如果线程处于睡眠状态,是否有什么我不应该做的事情,例如修改类范围内声明的静态集合?

while(true)
不同,
线程。睡眠不使用CPU周期,因此从这个意义上讲,睡眠更有效。一般来说,强烈反对在外部使用

如果线在睡觉,有什么我不应该做的吗

由于您的线程在进入
thread.Sleep
时被阻止,因此您希望对其资源执行的任何操作都是公平的。

while(true)
消耗CPU,而
sleep()
以更智能的方式工作:
sleep()
函数将当前执行上下文置于睡眠状态;它通过调用一个syscall来调用内核睡眠函数来实现这一点,而内核睡眠函数是原子性的
(a) 设置唤醒计时器
(b) 将当前进程标记为休眠
(c) 等待直到唤醒计时器触发或发生中断

如果调用
sleep()
,CPU可以执行其他工作

这就是
sleep()
有用的原因之一


一个有用的链接-

我建议使用
ManualResetEvent
(或其他
WaitHandle
)并调用

这将有一个类似于永远睡眠的效果,除了它提供了一个干净的方法,在需要时(通过调用事件)退出无限“阻塞”

使用
while(true)
将消耗CPU周期,因此这绝对是需要避免的

有什么我不应该做的,比如修改在类的作用域中声明的静态集合吗

一般来说,不会。因为您的线程将被阻止,所以使用共享数据不应该存在任何同步问题(前提是集合中的项目没有特定要求,例如必须在具有适当同步上下文的线程上使用的用户界面元素)。

我认为调用

while (true) { ... } 
是计算密集型的,因为线程永远不会停止

Thread.Sleep(Timeout.Infinite);
实际上,在操作系统本机调度器的帮助下使线程休眠。然后线程实际上停止了,所以我想它的计算要求比较低

调用Thread.Sleep方法会导致当前线程立即阻塞毫秒数或传递给该方法的时间间隔,并将其剩余的时间片传递给另一个线程

由于C#7.1,您可以使主方法异步。这意味着,您可以将Main方法作为任务异步挂起,而不是使用忙等待或线程锁定睡眠。这样,运行Main的线程就不会被锁定。使用
Cts.Cancel()
,您可以轻松释放主任务以退出应用程序(而不允许其他线程/任务完成工作)

自2020年以来,C#9.0,整个
程序.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);
如果无限睡眠取消是这种情况下的正常代码流,您可以尝试捕获任务取消异常(请不要使用
Task.Delay
inf sleep,如果您试图等待/同步其他任务,则尝试捕获效率较低,会使队友感到困惑):


谢谢,我已经看到while循环被推荐给那些试图完成我正在做的事情的人,我不确定这是否是正确的方法。实际上我根本不想让它退出,但我会接受你的回答,以防有人真的希望有办法退出。@Daniel很高兴有一个干净的方法让你的程序最终关闭,即使在任何特定的时间点你都不希望这样;)话虽如此,我个人还是会在睡眠时使用这种方法。如果程序关闭的唯一时间是机器重新启动时,那么使用ManualResetEvent与Thread.sleep()有什么不同呢?@Daniel我认为意图更清楚一些。它将具有相同的效果ManualResetEvent选项需要更多的字符,其意图并不比“无限睡眠”更清晰,但它确实感觉不那么像黑客。您的答案中似乎存在不确定性。。。“我想”、“我想”等等。我对答案很确定,但我刚开始在java工作,这就是为什么我使用“我想”、“我想”作为预防措施的原因。:)如何取消/停止它?
Cts.cancel()它抛出一个异常
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);
try
{
    await Task.Delay(Timeout.Infinite, Cts.Token).ConfigureAwait(false);
}
catch(TaskCanceledException) { /* Ignored */ }