具有Timer控制的线程池操作的C#WinService

时间:2011-01-20 13:38:42

标签: c# timer threadpool multithreading

我有一个Windows Service类(继承自ServiceBase),它在构造时提供了一个对象列表。 每个操作描述一个DoWork()虚拟方法 Service类的重点是管理所有底层操作,在运行时将它们添加到List中并在ThreadPool线程中执行它们的DoWork()方法。
每个Operation都有一个System.Timers.Timer对象,该对象被实例化并与Operation类一起运行。每个操作都会公开一个事件,通知管理类自己的计时器已启动,并且必须在线程中触发自己的DoWork()方法。

TimedService类将每个已用的计时器事件绑定到从池请求线程的方法:

private void CheckOperationsList(object source, EventArgs e)
{
 try
  {
    foreach (Operation op in this._operationsList)
    {
      lock (this._operationsList)
      {
        op.TimerElapsed += new Operation.ElapsedEventHandler(this.RequestThreadFromPool);
      }
    }
  }
  catch (Exception ex) { this._ManEV.WriteError(this._serviceName, ex.Message); }
}  

当然,RequestThreadFromPool(对象发送者,EventArgs e)方法执行以下操作:

    ThreadPool.QueueUserWorkItem(new WaitCallback(((Operation)sender).DoWork), new object());  

我从流程中收到了奇怪的行为。我试图实现一个虚拟操作,定时器设置为10秒,这只是让处理器占用几秒钟:

for (Int16 i = 0; i < Int16.MaxValue; i++)
  {
    for (short j = 0; j < short.MaxValue; j++)
    { }
  }  

每次操作在队列中单独运行时(我只将一个元素的List传递给服务)一切正常。该过程产生自己的线程,使CPU保持几秒钟,然后离开。

我实现了上面的虚拟方法的较轻版本(基本上没有内部循环)以模拟轻量级线程。

一旦我在队列中得到两个或更多个操作(使用不同的计时器!),所有线程都会产生三到四次,然后一切都停止。
我根本没有活动。在Visual Studio中,看起来每个操作的Timer都已停止滴答 - 我没有调用该事件,我没有调用应该处理该事件的委托;每个Operation类都有自己的定时器,并且总是通过它来引用定时器。 !

我尝试监控所有catch {} es,并尝试在try {}中包装每个DoWork()方法,但我没有例外。

让我感到困惑的是,如果我运行几个相同的操作(即两个或三个长操作或两个或三个短操作),一切都正常运行。看起来事件来自另一个类,一切都搞砸了。

我开始认为System.Timers.Timer类是上述所有原因 - 我在调用Event之前尝试将Stop()调用到计时器,但无济于事。 我得到每个Operation的DoWork()方法的4-5次迭代,然后一切都退了下来。

编辑我忘了澄清:我运行的每个操作都是从基本操作继承的。我:

public class TestLongOperation : Operation
{
  public TestLongOperation(double secondsInterval) : base(secondsInterval) { }
  public override void Work(object buh)
  {
    for (Int16 i = 0; i < Int16.MaxValue; i++)
    {
      for (short j = 0; j < short.MaxValue; j++)
      { }
  }
}

}

有什么建议吗?如果上述内容不足,我可以提供更多代码。 提前谢谢。

2 个答案:

答案 0 :(得分:1)

我有一种感觉,计时器在每个tick事件上创建一个新线程,我的服务有问题导致很多线程被生成,如果在下一个tick开始时仍有大量处理从前一个tick开始

我最终完全删除了计时器并用循环替换了它。然后在我的主处理线程中添加了一个Thread.sleep。然后它就像一个计时器,但不保持产生线程。此外,在处理完成之前,循环不会完成。

例如:

(主要的Thead)

bool running = true;

while (running)
{

  //do processing


  /sleep for 'timer' interval
  Thread.Sleep(interval)
}

这有帮助吗?

答案 1 :(得分:0)

一些随意的想法:

当程序挂起时,如果你在几条“锁定”线上,你是否会遇到休息和cheeck。

这些是一次性定时器吗?如果是这样,在启用计时器之前连接了事件处理程序。如果没有,你的工作是否可以重入?

在计时器处理程序中,为什么要生成另一个线程来完成工作?计时器已将其置于新线程中。也许你遇到线程池耗尽?如果几个timerhandler启动并耗尽线程池,那么它们将等待启动工作线程。

阅读Timer.SynchronizingObject Property 以查看Timer可以使用ThreadPool。