线程睡眠和Windows服务

Spe*_*ort 7 .net multithreading sleep windows-services timer

我正在开发一个有一些问题的Windows服务,Thread.Sleep()所以我想我会尝试使用计时器,因为这个问题建议:

在Windows服务中使用Thread.Sleep()

事情是我不清楚如何实现这一点.我相信这是方法,但我只想确保:

'' Inside The Service Object
Dim closingGate As System.Threading.AutoResetEvent

Protected Overrides Sub OnStart(ByVal args() As String)
   Dim worker As New Threading.Thread(AddressOf Work)
   worker.Start()
End Sub

Protected Sub Work()
   Dim Program = New MyProgram()
   closingGate = New System.Threading.AutoResetEvent(False)
   Program.RunService(closingGate)
End Sub

Protected Overrides Sub OnStop()
   closingGate.Set()
End Sub

'' Inside My Programs Code:
Public Sub RunService(closingGate As AutoResetEvent)
   Dim tmr As New Timer
   '' ...and so on

   closingGate.WaitOne()
End Sub
Run Code Online (Sandbox Code Playgroud)

除了使用VB.Net(开玩笑,但如果可以的话,我会使用C#.)我是否在正确的轨道上?这比使用更好Thread.Sleep()吗?

Aar*_*ght 19

老实说,我不得不说,我认为你在这里有点偏僻.

首先,发布的实际代码并没有多大意义; 工作线程正在等待信号但是没有任何理由 - 它实际上并不是在任何类型的循环中或等待资源.其次,如果您确实需要在收到关闭信号后在worker中执行一些(可能省略的)清理代码,那么您的服务可能不会给工作线程足够的时间来清理.

但是,从根本上说,你所做的就是将问题转移到一个单独的线程中.这可能使服务对服务控制器保持响应,但它不能解决设计问题 - 并且通过使用线程和互斥体会增加许多不必要的复杂性; 最终,如果你需要,它只会让你的服务更难调试.

假设您需要每5秒执行一些代码.这个想法是,不是"等待"5秒,而是反转控件,让计时器调用你的工作.

这是不好的:

protected override void OnStart(string[] args)
{
    while (true)
    {
        RunScheduledTasks();    // This is your "work"
        Thread.Sleep(5000);
    }
}
Run Code Online (Sandbox Code Playgroud)

这很好:

public class MyService : ServiceBase
{
    private Timer workTimer;    // System.Threading.Timer

    protected override void OnStart(string[] args)
    {
        workTimer = new Timer(new TimerCallback(DoWork), null, 5000, 5000);
        base.OnStart(args);
    }

    protected override void OnStop()
    {
        workTimer.Dispose();
        base.OnStop();
    }

    private void DoWork(object state)
    {
        RunScheduledTasks();  // Do some work
    }
}
Run Code Online (Sandbox Code Playgroud)

而已.这就是你要定期工作的全部工作.只要工作本身一次不运行几秒钟,您的服务将保持对服务控制器的响应.在这种情况下,您甚至可以支持暂停:

protected override void OnPause()
{
    workTimer.Change(Timeout.Infinite, Timeout.Infinite);
    base.OnPause();
}

protected override void OnContinue()
{
    workTimer.Change(0, 5000);
    base.OnContinue();
}
Run Code Online (Sandbox Code Playgroud)

您需要在服务中开始创建工作线程的唯一时间是工作本身可以运行很长时间,并且您需要能够在中间取消.这往往涉及大量的设计工作,所以如果不确定它与您的场景有关,我就不会深入研究.

除非你真的需要,否则最好不要开始在你的服务中引入多线程语义.如果你只是想安排小工作单元,你肯定不需要它.