【问题标题】:Issue with ballooning threads in periodic processing周期性处理中的膨胀线程问题
【发布时间】:2013-06-13 16:32:03
【问题描述】:

我想在工作完成时发出信号的工作线程上做一些定期工作。收到信号后,我想等待 5 秒钟,然后重新开始工作。我写了以下代码:

public class WinService : ServiceBase
{
    private readonly ManualResetEvent stopPeriodicProcess = new ManualResetEvent(false);

    protected override void OnStart(string[] args)
    {
        stopPeriodicProcess.Reset();
        ThreadPool.RegisterWaitForSingleObject(stopPeriodicProcess, InitializeEngines, null,5000, true);          
    }

    public void InitializeEngines(object state, bool timedOut)
    {       
        engine.LoadSettings();

        Task.Factory.StartNew(engine.DoSomeWork); //Fire and forget     
    }

    private void WorkCompletedEventHandler(object sender, WorkCompletedEventArgs e)
    {
        ThreadPool.RegisterWaitForSingleObject(stopPeriodicProcess,
                                               (state, timedOut) => DoPeriodicProcess(state, timedOut, e.EngineId), null,
                                               5000, true);
    }

    public void DoPeriodicProcess(object state, bool timedOut, string engineId)
    {
        if (timedOut)
        {                
            Task.Factory.StartNew(engine.DoSomeWork); //Fire and forget
        }
    }
}


public class Engine
{
    public event EventHandler<WorkCompletedEventArgs> WorkCompleted;    
    public void DoSomeWork()
    {
        //Doing some work..

        //Raise an event to signal that the work has been completed
        var args = new WorkCompletedEventArgs {EngineId = Settings.EngineId};
        RaiseWorkCompletedEvent(args);
    }

    protected virtual void RaiseWorkCompletedEvent(WorkCompletedEventArgs e)
    {
        EventHandler<WorkCompletedEventArgs> handler = WorkCompleted;
        if (handler != null)
        {
            handler(this, e);
        }
    }   
}

当我运行代码时,几秒钟后 CPU 使用率显示为 100%。在 VS 中调试时,我看到太多的工作线程在 WorkCompletedEventHandler 内的 RegisterWaitForSingleObject 处等待。

为什么在调用 RegisterWaitForSingleObject 后线程没有死掉?我错过了什么吗?

【问题讨论】:

  • 你能提供真正符合要求的代码吗?在您的代码中,engine 字段缺失,QueueEmptied 事件不存在且从未订阅。
  • 更新了代码以具有 WorkCompleted 事件处理程序。我在 LoadSettings 中订阅它:engine.WorkCompleted += WorkCompletedEventHandler;

标签: c# multithreading task-parallel-library periodic-processing


【解决方案1】:

未测试,但我认为这是由于事件未重置

private void WorkCompletedEventHandler(object sender, WorkCompletedEventArgs e)
{
    stopPeriodicProcess.Reset();
    ThreadPool.RegisterWaitForSingleObject(stopPeriodicProcess,
                                           (state, timedOut) => DoPeriodicProcess(state, timedOut, e.EngineId), null,
                                           5000, true);
}

此外,我不明白您为什么要这样做,您不能使用专为这种用例设计的计时器吗?

【讨论】:

  • 这没有任何意义。在代码中,Set() 不会在任何地方调用,因此永远不会设置事件。
  • 我尝试了重置。它没有帮助。计时器是指 System.Timers.Timer 还是 System.Threading.Timer ?
猜你喜欢
  • 1970-01-01
  • 2014-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多