1

我被告知制作 Windows 服务的方式如下:

Thread serviceThread = new Thread(new Thread(runProc())
Boolean isRunning = true;

if (_isRunning)
   {
      serviceThread.Start();
   }else
      close and log service

void runProc()
{
   while(_isRunning)
   {
      //Service tasks
   }

   _isRunning = false;
}

到目前为止,这对我来说效果很好,但现在我需要做一个有重大突破的服务,一次最多 2 小时。此外,我已经开始使用计时器,因此除了停止 runProc() 一遍又一遍地运行之外,在无限循环中没有做任何事情,我可以想象这是不好的,因为正在制作和重新制作线程很多。

我的问题是,我已经读过将 Thread.Sleep(big number) 放在那个 while(_isRunning) 无限循环中是不好的做法,这是真的吗?如果是这种情况,我如何绕过不断运行的循环并使用大量资源?现在在循环中实际上没有做任何事情,这一切都在我的计时器的滴答事件中处理,我有一个循环的唯一原因是停止 runProc 结束。

非常感谢,如果我解释得不好,很抱歉

4

2 回答 2

2

Thread.Sleep不好,因为它不能(容易)被打断1

我通常更喜欢使用 aManualResetEvent或类似的:

class abc {
  Thread serviceThread = new Thread(new Thread(runProc())
  ManualResetEvent abort = new ManualResetEvent(false);

  void Start(){
      serviceThread.Start();
  }
  void Stop(){
     abort.Set();
     serviceThread.Join();
  }
  void runProc()
  {
     while(!abort.WaitOne(delay))
     {
      //Service tasks
     }
  }
}

希望你能明白要点,而不是一个很好的代码示例。

可以任意大delay或小(并且可以在每个循环期间任意重新计算)。该WaitOne调用将延迟此线程的进度delay几毫秒,或者如果Stop被调用,将导致循环立即退出。


1从下面的评论中总结我的立场 - 它只能被生硬的工具打断,Thread.Abort或者Thread.Interrupt它们都共享失败(或多或少),他们也可以在代码中的其他各个地方引入相关的异常。如果你能保证线程实际上在Thread.Sleep调用内部,那么后者可能没问题——但如果你能做出这样的保证,你通常也可以安排使用不那么生硬的线程间通信机制——比如我的那个我在这个答案中提出了建议。

于 2013-10-28T15:10:24.933 回答
0

我总是用主无限循环而不是计时器编写服务。在循环内部,我检查是否有任何工作要做,如果有,我会做工作,如果没有,我会调用Thread.Sleep(). 这意味着只要有工作要做,循环就会不断迭代,尽可能快地运行。当工作队列“干涸”时,它会休眠一点(几秒钟或几分钟),同时有更多工作可用。

对于服务器上的后端作业来说,这总是非常有效,因为在整个白天(和晚上)都有源源不断的新工作要做。如果您有很长一段时间没有工作,该服务将多次唤醒以检查,然后重新进入睡眠状态。你可能喜欢也可能不喜欢。只要检查速度快,应该不是问题。另一种方法是使用计划任务(或数据库作业),以便您知道工作将在一天中的特定时间完成。在某些情况下,这是一种更好的方法。

于 2013-10-28T15:11:52.753 回答