“while(true){Thread.Sleep}”的原因是什么?

时间:2014-05-12 18:45:15

标签: c# multithreading azure-worker-roles

我有时会遇到以下形式的代码:

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);
}

我认为有更好的方法来阻止服务(或天蓝色工作者角色)退出。 有人对我有建议吗?

7 个答案:

答案 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
  • 如果代码正在等待线程或进程完成,或者网络事件发生,请使用相应的synchronization primitiveWaitOne()WaitAny()WaitAll()作为适当。如果在循环中使用带超时的重载,它也会为您提供可取消性。

但是,如果不了解实际情况,很难断然说它既好又坏或无动于衷。如果你有一个守护进程正在运行,必须定期轮询(比如一个NTP客户端),那么这样的循环就会很有意义(尽管守护进程会需要一些逻辑来监视发生的关闭事件。)即使有类似的东西,你也可以用计划任务替换它:一个不同但不一定更好的设计。

答案 4 :(得分:1)

答案 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);
}