1

我有一个可以托管一个或多个后台线程的 Windows 服务。每个后台线程启动一个轮询循环来检查工作。我一直在使用以下模式来实现循环:

new Thread(DoWork).Start();

private void DoWork()
{
    while(keepRunning)
    {
        Console.WriteLine(DateTime.Now);
        Thread.Sleep(1000);
    }
}

我正在尝试找到一种消耗更少 CPU 的替代方案。我已经能够使用带有递归方法的计时器来实现轮询循环:

var timer = new Timer(WakeUp, null, Timeout.Infinite, 1000)
timer.Change(0, 1000);

private void WakeUp(object state)
{
    lock (locker)
        Monitor.Pulse(locker);
}

private void DoWork()
{
    lock (locker)
    {
        if (!keepRunning) return;
        Console.WriteLine(DateTime.Now);
        Monitor.Wait(locker);
        DoWork();
    }
}

使用一种模式比另一种模式有什么优势吗?在后台线程中设置轮询循环是否有更好的模式?

4

1 回答 1

3

我正在尝试找到一种消耗更少 CPU 的替代方案。

您是否有任何证据表明它目前实际上正在消耗大量 CPU?除非您有很多线程在相似的时间醒来并竞争,否则我希望Thread.Sleep它会相当有效。

您的递归DoWork方法要糟糕得多-除非它经过尾调用优化,否则您最终会因堆栈溢出而崩溃。你为什么不至少循环?为什么不直接在计时器线程中进行实际工作呢?

如果您真的希望每个任务一个线程,每秒执行一次工作,那么您的第一个代码是可以的(尽管您需要确保“看到”任何新值,keepRunning如果它只是一个字段 - 考​​虑使用Interlocked)。但理想情况下,您根本不应该拥有这些线程 - 只需使用适当的计时器来安排每秒一次的工作,并让线程池处理它。

于 2012-10-22T22:23:40.877 回答