C# “为什么?”;而(true){Thread.Sleep}";?
我有时会遇到以下形式的代码:C# “为什么?”;而(true){Thread.Sleep}";?,c#,multithreading,azure-worker-roles,C#,Multithreading,Azure Worker Roles,我有时会遇到以下形式的代码: while (true) { //do something Thread.Sleep(1000); } ClassXYZ xyz = new ClassXYZ(); //ClassXYZ creates separate Threads which execute code while (true) { Thread.Sleep(1000); } 我想知道这被认为是好的还是坏的做法,是否有其他选择 通常我在服务的主要功能中“找到”这样的代码 我最近在
while (true) {
//do something
Thread.Sleep(1000);
}
ClassXYZ xyz = new ClassXYZ(); //ClassXYZ creates separate Threads which execute code
while (true) {
Thread.Sleep(1000);
}
我想知道这被认为是好的还是坏的做法,是否有其他选择
通常我在服务的主要功能中“找到”这样的代码
我最近在windows azure worker角色的“Run”函数中看到了以下形式的代码:
while (true) {
//do something
Thread.Sleep(1000);
}
ClassXYZ xyz = new ClassXYZ(); //ClassXYZ creates separate Threads which execute code
while (true) {
Thread.Sleep(1000);
}
我认为有更好的方法来防止服务(或azure worker角色)退出。
有人对我有什么建议吗?如果您使用而(true)
您没有从循环外部结束循环的编程方法
至少,我更喜欢while(mySingletonValue)
,它允许我们根据需要切换循环
另一种方法是从循环行为中删除函数行为。您的循环仍然是无限的,但它调用了在别处定义的函数。因此,循环行为与循环执行的内容完全隔离:
while(GetMySingletonValue())
{
someFunction();
}
这样,您的单例就可以完全控制循环行为。这实际上取决于它如何决定何时中断循环
一般来说,更合适的方法是使用一些同步原语(如
ManualResetEvent
)等待,处理和触发循环中断的代码(在另一个线程上)向该原语发送信号。这样,您就不会因为被安排在每秒钟内什么都不做而浪费线程资源,而且是一种更干净的方式。当您使用thread.Sleep(1000)
执行此操作时,您的处理器会浪费少量时间来唤醒并什么都不做
你可以用它做类似的事情
当您调用WaitOne()
时,它将等待直到收到信号
CancellationTokenSource cancelSource = new CancellationTokenSource();
public override void Run()
{
//do stuff
cancelSource.Token.WaitHandle.WaitOne();
}
public override void OnStop()
{
cancelSource.Cancel();
}
这将防止Run()方法退出,而不会将CPU时间浪费在繁忙的等待上。另一种方法可能是使用
AutoResetEvent
并在默认情况下实例化它
public class Program
{
public static readonly AutoResetEvent ResetEvent = new AutoResetEvent(true);
public static void Main(string[] args)
{
Task.Factory.StartNew
(
() =>
{
// Imagine sleep is a long task which ends in 10 seconds
Thread.Sleep(10000);
// We release the whole AutoResetEvent
ResetEvent.Set();
}
);
// Once other thread sets the AutoResetEvent, the program ends
ResetEvent.WaitOne();
}
}
所谓的while(true)
是一种不好的做法吗?
嗯,事实上,字面上的true作为,而循环条件可能被认为是一种不好的做法,因为它是一个不可中断的循环:我总是使用一个可变条件,它可能导致true
或false
我什么时候会使用while
循环或类似AutoResetEvent
的方法?
何时使用而循环。。。
…当您需要在等待程序结束时执行代码时
何时使用AutoResetEvent
方法。。。
…当您只需要保持主线程以防止程序结束,但这样的主线程只需要等待其他线程请求程序退出。我个人不喜欢线程。睡眠代码。因为它锁定了主线程。如果它是一个windows应用程序,您可以编写类似的内容,它允许您更灵活地使用,并且您可以将其称为async:
bool switchControl = true;
while (switchControl) {
//do something
await Wait(1);
}
async void Wait(int Seconds)
{
DateTime Tthen = DateTime.Now;
do
{
Application.DoEvents(); //Or something else or leave empty;
} while (Tthen.AddSeconds(Seconds) > DateTime.Now);
}
如果您看到这样的代码
while (true)
{
//do something
Thread.Sleep(1000);
}
它最有可能使用Sleep()
作为等待某个事件发生的一种手段,例如用户输入/交互、文件系统中的更改(例如文件夹中创建或修改的文件、网络或设备事件等)。这将建议使用更合适的工具:
- 如果代码正在等待文件系统中的更改,请使用
- 如果代码正在等待线程或进程完成,或网络事件发生,请使用适当的and
WaitOne()
,WaitAny()
或WaitAll()
。如果在循环中使用带超时的重载,也可以取消
但是在不知道实际上下文的情况下,很难明确地说它是好的、坏的还是无关紧要的。如果您有一个运行的守护进程必须定期轮询(比如NTP客户端),那么这样的循环将非常有意义(尽管守护进程需要一些逻辑来监视发生的关闭事件)即使是这样,你也可以用一个预定的任务来代替它:一个不同但不一定更好的设计。有更好的方法来保持Azure服务并在需要时退出
参考:
使用计时器可能是更好的选择。请参阅while(true)
部分在适当的情况下可能非常合适。Thread.Sleep()
部分更值得怀疑。switch不是一个保留关键字吗?我非常喜欢这个答案,因为它非常简单,非常适合消除while(true)在我的第二个例子中,如果可以的话,我会接受更多的答案。