我有时会遇到以下形式的代码:
while (true) {
//do something
Thread.Sleep(1000);
}
我想知道这是否被认为是好的或坏的做法,以及是否有其他选择。
通常我会在服务的主要功能中“找到”这样的代码。
我最近在windows azure worker角色的“运行”功能中看到了具有以下形式的代码:
ClassXYZ xyz = new ClassXYZ(); //ClassXYZ creates separate Threads which execute code
while (true) {
Thread.Sleep(1000);
}
我认为有更好的方法来阻止服务(或天蓝色工作者角色)退出。 有人对我有建议吗?
答案 0 :(得分:9)
当你使用Thread.Sleep(1000)
执行此操作时,您的处理器会浪费很少的时间来唤醒并且什么都不做。
您可以使用CancelationTokenSource执行类似操作。
当你致电WaitOne()
时,它会等到收到信号。
CancellationTokenSource cancelSource = new CancellationTokenSource();
public override void Run()
{
//do stuff
cancelSource.Token.WaitHandle.WaitOne();
}
public override void OnStop()
{
cancelSource.Cancel();
}
这样可以防止Run()方法退出,而不会在忙碌的等待中浪费你的CPU时间。
答案 1 :(得分:3)
另一种方法可能是使用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)
是一种不良做法吗?嗯,事实上,一个真正的while
循环条件可能被认为是一种不好的做法,因为它是一个不可破解的循环:我总是使用一个可变条件,这可能导致{{1 }或true
。
false
循环或类似while
方法时?AutoResetEvent
循环... ...当你需要在等待程序结束时执行代码时。
while
方法...... ...当你只需要保持主线程以防止程序结束时,但是这样的主线程只需要等到其他线程请求程序退出。
答案 2 :(得分:1)
如果使用while(true)
,则没有编程方法可以从循环外部结束循环。
我更喜欢while(mySingletonValue)
,这样我们就可以根据需要切换循环。
另一种方法是从循环行为中删除功能行为。你的循环仍然是无限的,但它调用其他地方定义的函数。因此,循环行为与循环执行的内容完全隔离:
while(GetMySingletonValue())
{
someFunction();
}
通过这种方式,您的单例完全控制循环行为。
答案 3 :(得分:1)
如果你看到这样的代码......
while (true)
{
//do something
Thread.Sleep(1000);
}
最有可能使用Sleep()
作为等待发生某些事件的方式 - 例如用户输入/交互,文件系统中的更改(例如在文件夹,网络或设备事件中创建或修改的文件等。这会建议使用更合适的工具:
FileSystemWatcher
。WaitOne()
,WaitAny()
或WaitAll()
作为适当。如果在循环中使用带超时的重载,它也会为您提供可取消性。但是,如果不了解实际情况,很难断然说它既好又坏或无动于衷。如果你有一个守护进程正在运行,必须定期轮询(比如一个NTP客户端),那么这样的循环就会很有意义(尽管守护进程会需要一些逻辑来监视发生的关闭事件。)即使有类似的东西,你也可以用计划任务替换它:一个不同但不一定更好的设计。
答案 4 :(得分:1)
有更好的方法可以保留Azure服务并在需要时退出。
参见:
答案 5 :(得分:0)
它确实取决于//do something
如何确定何时突破循环。
一般来说,更合适的方法是使用一些同步原语(如ManualResetEvent
)等待,以及处理和触发循环中断的代码(在另一个线程上)该原语上的信号。通过这种方式,您可以通过每秒安排无所事事来消耗线程浪费资源,并且这是一种更清晰的方法。
答案 6 :(得分:0)
我个人不喜欢Thread.Sleep代码。因为它锁定了主线程。你可以写这样的东西,如果它是一个Windows应用程序,除了它允许你更灵活,你可以称之为异步:
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);
}