轮询的线程实践

时间:2010-04-30 16:21:44

标签: c# multithreading

我有一个C#应用程序,必须不断读取程序;有时候它有可能找不到它需要的东西,这会引发异常。这是它必须阅读的程序的限制。

这经常导致程序在尝试轮询时锁定。所以我通过将'轮询'产生到一个单独的线程来解决它。但是,观察调试器时,每次都会创建并销毁该线程。我不确定这是否典型;但我的问题是,这是一个好的做法,还是我使用线程是为了错误的目的?

ProgramReader
{ 
  static Thread oThread;
  public static void Read( Program program )
  {
    // check to see if the program exists
    if ( false )
      oThread = new ThreadStart(program.Poll);
    if(oThread != null || !oThread.IsAlive )
      oThread.Start();
  }
}

这是我的一般伪代码。它每10秒左右运行一次。这对性能有很大影响吗?它执行的操作相对小而轻;只是重复。

2 个答案:

答案 0 :(得分:4)

Thread无法“重新启动”,这就是您在调试器中看到的内容。这是正常行为,但我担心这里有两个问题:

  1. 你具体说明Program有时候会抛出一个异常,但你实际上并没有抓住它。后台线程上未处理的异常会降低整个过程。

  2. 无论情况如何,都会产生线程。目前尚不清楚Program.Poll是否实际上是线程安全的(我的猜测是否定的),即使它是,你也可能不想用这些请求充斥系统。

  3. 更好的设计可能是这样的:

    private AutoResetEvent polledEvent = new AutoResetEvent(true);
    
    public void Read(Program program)
    {
        polledEvent.WaitOne();
        ThreadPool.QueueUserWorkItem(s => 
        {
            try
            {
                program.Poll();
            }
            catch (PollingException ex)
            {
                // Handle the exception
            }
            polledEvent.Set();
        });
    }
    

    这将通过处理任何异常以及限制可能同时发生的轮询请求的数量来解决上述两个问题。它还使用ThreadPool重新使用线程。

    如果Poll方法确实是线程安全的,并且您可以将多个请求排队,请将AutoResetEvent更改为Semaphore并使用实际的实际数量初始化它要求你想要同时发生。

    最后一点:如果在Windows窗体,Windows服务或WPF应用程序中发生这种情况,我建议使用BackgroundWorker而不是滚动自己的线程代码。大部分工作已在那里为您完成,您只需要在DoWork事件处理程序中编写轮询循环。

答案 1 :(得分:0)

创建一个等待和休眠的线程,或者使用ThreadPool,这听起来像是为你的任务做的事情。