C# 检查控制计时器的线程的状态

C# 检查控制计时器的线程的状态,c#,.net,multithreading,windows-services,timer,C#,.net,Multithreading,Windows Services,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

我正在使用线程定期运行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而不是计时器,这意味着一切都在单个线程中运行,而不是线程池中的单个线程,我可以查询线程的线程状态。现在我正在使用计时器,线程状态将停止,因为一旦计时器启动,线程将停止


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

让线程更新Windows服务可见的某个值,如果该值未更新,则表示线程已停止。我不知道还有什么其他方法可以监控计时器

让线程更新Windows服务可见的某个值,如果该值未更新,则表示线程已停止。我不知道还有什么其他方法可以监控计时器

您可以在contents main循环周围添加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的执行是否被挂起,或者计时器是否由于某种不明原因没有重新启动。

您可以在内容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的执行是否被挂起,或者计时器是否因为某种模糊的原因没有重新启动。

我会采取另一种方法,创建您自己的线程,并使用回调来发出线程已完成的信号。回调会传回一个结果,主线程使用该结果来决定要做什么。你甚至不需要一个定时器来完成这项工作,尽管你可以用它来让你的工人在一段时间内开火

下面是一个示例,它使用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);
        }
    }
}

我会采取另一种方法,创建自己的线程,并使用回调来表示线程已经完成。回调会传回一个结果,主线程使用该结果来决定要做什么。你甚至不需要一个定时器来完成这项工作,尽管你可以用它来让你的工人在一段时间内开火

下面是一个示例,它使用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);
        }
    }
}

循环没有在任何特定线程上运行。当计时器周期结束时,MainLoop将在第一个可用的线程池线程上执行。如果您的程序中还有其他事情,MainLoop很可能在下次调用时在不同的线程上执行。您无法监视线程。下面的答案表明,使用最后一次运行时间可能是获得所需效果的最简单方法。主循环大部分时间都在做什么工作?处理文件?民意调查数据库?处理网络请求?执行计算任务?如果循环没有运行,你想做什么?@Jason主循环正在轮询数据库。我有两个服务在不同的服务器上运行,一个是主动的,一个是被动的。被动服务器通过TCP轮询主动服务,如果发现循环已停止,则应作为主动服务器接管。循环未在任何特定线程上运行。当计时器周期结束时,MainLoop将在第一个可用的线程池线程上执行。如果您的程序中还有其他事情,MainLoop很可能在下次调用时在不同的线程上执行。您无法监视线程。下面的答案表明,使用最后一次运行时间可能是获得所需效果的最简单方法。主循环大部分时间都在做什么工作?处理文件?民意调查数据库?处理网络请求?执行计算任务?如果循环没有运行,你想做什么?@Jason主循环正在轮询数据库。我有两个服务在不同的服务器上运行,一个是主动的,一个是被动的。被动式通过TCP轮询主动式服务,如果它发现循环已停止,那么它将作为主动式服务接管。我愚蠢地没有想到用try…catch来包装整个内容。我愚蠢地没有想到用try…catch来包装整个内容。我将采用Brian的答案,因为它更简单,但谢谢很多。我同意布赖恩的答案,因为它更简单,但非常感谢。