【问题标题】:What is a better way to stop this worker thread?停止此工作线程的更好方法是什么?
【发布时间】:2014-03-19 16:45:40
【问题描述】:

我正在开发一个应用程序,它会定期轮询 Web 服务以获取某些数据。应用程序必须作为 Windows 服务运行,因此必须以异步方式启动和停止。我正在为此使用线程。

工作线程的主循环是这样操作的:

bool stop = false;
int interval = 60000;    // 60 seconds, customizable

while(!stop)
{
    try
    {
        // Query the web service using a WebRequest
    }
    catch(Exception e)
    {
        // Handle exception
    }

    // Process data

    try
    {
        Thread.Sleep(interval);
    }
    catch(ThreadInterruptedException)
    {}
}

为了停止工作线程,我从控制线程执行此操作:

stop = true;
workerthread.Interrupt();
workerthread.Join();

这非常有效...除非在调用Thread.Interrupt() 时工作线程碰巧正在执行(或尚未执行)Web 请求;在这种情况下,真正被中断的是 Web 请求(可能会自行休眠),并且下一个 Sleep() 必须等到其常规超时才能退出。

有什么更好的方法来实现这一点并避免在错误的地方中断工作线程?

【问题讨论】:

  • 如果您的服务所做的只是睡眠并定期轮询,那么它应该是计划任务而不是服务。见Programs are not cats

标签: .net multithreading httpwebrequest webrequest


【解决方案1】:

使用MaualResetEvent

在启动线程的类中:

ManualResetEvent evt = new ManualResetEvent(false);

然后将你的代码修改为:

int interval = 60000;    // 60 seconds, customizable

while(evt.WaitOne(interval))
{
    try
    {
        // Query the web service using a WebRequest
    }
    catch(Exception e)
    {
        // Handle exception
    }

    // Process data
}

要停止线程,只需调用evt.Set();

这将导致线程停止,即使它处于 60 秒等待的中间。

【讨论】:

  • 调用evt.Set()时,如果工作线程还没有等待会发生什么?
  • 下次它到达 while 循环的顶部时,它将立即停止。您的流程的每个循环是否需要很长时间?
  • 不,最多几秒钟;完成运行循环,到达下一个WaitOne()时退出即可。
  • 效果很好,我只移动了循环底部的睡眠,以便立即开始第一个工作循环。
  • 你实际上也可以 WaitOne 为 0 毫秒。当我需要这样做时,我通常定义一个 bool 来跟踪它是否是第一个循环,然后执行 WaitOne(isFirst?0:interval)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多