Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “为什么?”;而(true){Thread.Sleep}";?_C#_Multithreading_Azure Worker Roles - Fatal编程技术网

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)在我的第二个例子中,如果可以的话,我会接受更多的答案。