2011-01-20 63 views
3

我有一个Windows Service类(从ServiceBase继承),它在构造时提供了一个对象列表。每个操作描述一个DoWork()虚拟方法。
服务类的要点是管理所有底层操作,在运行时将它们添加到列表中或将它们移除到列表中,并在ThreadPool线程中执行它们的DoWork()方法。
每个操作都有一个System.Timers.Timer对象,它被实例化并与Operation类一起运行。每个操作暴露了一个事件,以向管理类发出自己的计时器已启动并且必须在线程中激发自己的DoWork()方法的信号。具有定时器控制的线程池操作的C#WinService

的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的)方法执行以下操作的事:

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++) 
    { } 
    } 

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

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

只要我在队列中有两个或更多的操作(使用不同的定时器!),所有线程产生三到四次,然后一切都停止。
我根本没有活动。在Visual Studio中,它看起来像每个操作的计时器已停止滴答滴答 - 我没有收到任何事件调用,也没有收到任何应付事件的委托的调用;每个操作类都有自己的定时器,并且通常通过此参考定时器。 !

我试着监视所有catch {} es,并尝试在try {}中包装每个DoWork()方法,但我没有得到任何异常。

令我困惑的是,如果我运行几个相同的操作(即两个或三个长操作或两个或三个短操作),一切都正常运行。看起来事件来自另一个班级,一切都会变得混乱。

我开始认为System.Timers.Timer类是所有上述的原因 - 我曾尝试在调用Event之前调用Stop()给计时器,但无济于事。 我得到了每个操作的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++) 
     { } 
    } 
} 

}

有什么建议?如果上述不足,我可以提供更多的代码。 在此先感谢。

+0

你从http://quartznet.sourceforge.net/试过quartz.net吗? Quartz.net的StatefulJob应该可以帮助你。还请检查我的一个帖子在这里:http://stackoverflow.com/questions/3995562/what-happens-in-quartz-net-quartz-when/4225590#4225590 – 2011-01-20 14:16:38

+0

我会看看它,但我希望通过自己做一点点学习。谢谢! – SimoneF 2011-01-20 14:38:43

回答

1

我有一种感觉计时器在每个滴答事件上创建一个新的线程,我的服务有一个问题,导致大量的线程被产生,如果大量的处理仍在继续从上一个滴答滴答下一个滴答开始。

我最终完全删除了定时器,并用循环替换它。然后在我的主要处理线程中添加了一个Thread.sleep。这就像一个计时器,但不会产生线程。此外,循环直到处理完成才会结束。

如:

(主要THEAD)

bool running = true; 

while (running) 
{ 

    //do processing 


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

有何帮助呢?

+0

这正是我认为正在发生的事情。 System.Threading.Timer应该做同样的事情。在最初的实现中,监督类有自己的计时器,所有的操作仅仅是DoWork()方法的包装器,拥有nextRun DateTime属性和Interval属性;每次迭代,监督器循环遍历队列,运行已过期的DoWork()线程,并将Interval添加到NextRun属性,但我希望线程本来是一个更好的实现(轮询或运行无限,而听起来不正确)。谢谢! – SimoneF 2011-01-20 13:53:08

0

一些随机的想法:

当程序挂起,你打突破和cheeck如果你是一对夫妇的“锁定”行。

这是一个定时器吗?如果是这样,在启用定时器之前,请连接事件处理程序。如果不是,你的工作是否可重入?

在计时器处理程序中,为什么会产生另一个线程来完成这项工作?计时器已经把它放在一个新的线程中。也许你打线程池耗尽?如果多个定时器处理程序启动并使用了线程池,那么它们将等待启动工作线程。

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