检查正在控制计时器的线程的状态

时间:2011-07-13 13:16:04

标签: c# .net multithreading windows-services timer

我正在使用Threading.Timer定期在Windows服务中运行一个线程,如下所示:

private Timer _timer;

public void Start()
{
    _timer = new Timer(MainLoop, null, 0, Timeout.Infinite);
}

private void MainLoop(object state)
{
    // Do something and then tell Timer to wait for a second
    _timer.Change(1000, Timeout.Infinite);
}

public void Stop()
{
    _timer.Change(Timeout.Infinite, Timeout.Infinite);
}

我的问题是,我希望Windows服务能够监视循环正在运行的线程,并在发现已停止的情况下执行某些操作。

以前我使用的是Thread.Sleep而不是Timer,这意味着所有内容都运行在单个线程中,而不是线程池中的单个线程,我可以查询Thread的ThreadState。现在我正在使用Timer,ThreadState被“停止”,因为一旦Timer启动,Thread就会停止。

那么在使用Threading.Timer时,确认线程是否仍在运行的最佳方法是什么?

3 个答案:

答案 0 :(得分:3)

您可以在内容MainLoop周围添加一个try-finally块,以保证计时器始终重新启动。

private void MainLoop(object state)
{
  try
  {
    // Do something and then tell Timer to wait for a second
  }
  finally
  {
    _timer.Change(1000, Timeout.Infinite);
  }
}

如果您仍然认为需要监控此方法的执行情况,则可以跟踪方法的上次启动时间。

private void MainLoop(object state)
{
  _lastRunTime = DateTime.UtcNow;
  try
  {
    // Do something and then tell Timer to wait for a second
  }
  finally
  {
    _timer.Change(1000, Timeout.Infinite);
  }
}

然后您可以使用_lastRunTime并将其与当前时间进行比较,以查看MainLoop的执行是否挂断或计时器(由于某些不明原因)未重启。

答案 1 :(得分:2)

让线程更新一些Windows服务可见的值,如果值未更新,则表示线程已停止。我不知道监视计时器的任何其他方法

答案 2 :(得分:0)

我采取不同的方法,创建自己的线程并使用回调来表示线程已完成。回调传回主线程用来决定做什么的结果。您甚至不需要计时器来执行此操作,但您可以使用一个计时器使您的工作人员间隔开火。

这是一个使用WaitHandle向主管发出信号已经完成的示例。

class Supervisor
{
    EventWaitHandle waitHandle = new AutoResetEvent(false);

    public bool Success { get; set; }

    // launch worker thread and wait for result
    public void Start()
    {
        while (true)
        {
            Thread thread = new Thread(() => { new Worker(new DoneDelegate(WorkerDone)).DoWork(); });
            thread.IsBackground = true;
            thread.Start();
            waitHandle.WaitOne(); // wait for worker to finish
            if (!Success) break; // handle error here
        }
    }

    // callback for worker to report result
    public void WorkerDone(bool successArg)
    {
        Success = successArg;
        // wake up supervisor
        waitHandle.Set();
    }
}

public delegate void DoneDelegate(bool successArg);
class Worker
{
    public DoneDelegate Done { get; set; }
    public Worker(DoneDelegate doneArg)
    {
        Done = doneArg;
    }

    public void DoWork()
    {
        // simulate work and exception
        Random rnd = new Random();
        Thread.Sleep(1000);
        try
        {
            int i = 10 / (1 - new Random().Next(5));
            Done(true);
        }
        catch
        {
            Done(false);
        }
    }
}