CPU友好的无限循环

Adi*_*Adi 53 .net c# console-application infinite-loop

编写无限循环很简单:

while(true){
    //add whatever break condition here
}
Run Code Online (Sandbox Code Playgroud)

但这会破坏CPU的性能.此执行线程将尽可能多地从CPU的电源中获取.

降低对CPU影响的最佳方法是什么?添加一些Thread.Sleep(n)应该可以解决问题,但为Sleep()方法设置高超时值可能表示对操作系统的应用程序无响应.

假设我需要在控制台应用程序中每分钟执行一次任务.我需要继续Main()在"无限循环"中运行,而计时器将触发将完成工作的事件.我想保持Main()对CPU的最小影响.

你有什么方法可以建议.Sleep()可以,但正如我已经提到的,这可能表明操作系统没有响应.

后期编辑:

我想更好地解释一下我在寻找什么:

  1. 我需要一个控制台应用程序不是Windows服务.控制台应用程序可以使用Compact Framework模拟Windows Mobile 6.x系统上的Windows服务.

  2. 只要Windows Mobile设备运行,我需要一种方法让应用程序保持活动状态.

  3. 我们都知道控制台应用程序运行只要其静态Main()函数运行,所以我需要一种方法来阻止Main()函数退出.

  4. 在特殊情况下(例如:更新应用程序),我需要请求应用程序停止,因此我需要无限循环并测试某些退出条件.例如,这就是为什么Console.ReadLine()我没用.没有退出条件检查.

  5. 关于上面,我仍然希望Main()函数尽可能地对资源友好.让我们确定检查退出条件的函数的指纹.

Oli*_*ver 51

要避免无限循环,只需使用a WaitHandle.要让流程退出外部世界,请使用EventWaitHandle带有唯一字符串的字符串.以下是一个例子.

如果你是第一次启动它,它会简单地每隔10秒打印一条消息.如果你在同一时间开始程序的第二个实例,它将通知另一个进程优雅地退出并立即退出.此方法的CPU使用率:0%

private static void Main(string[] args)
{
    // Create a IPC wait handle with a unique identifier.
    bool createdNew;
    var waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, "CF2D4313-33DE-489D-9721-6AFF69841DEA", out createdNew);
    var signaled = false;

    // If the handle was already there, inform the other process to exit itself.
    // Afterwards we'll also die.
    if (!createdNew)
    {
        Log("Inform other process to stop.");
        waitHandle.Set();
        Log("Informer exited.");

        return;
    }

    // Start a another thread that does something every 10 seconds.
    var timer = new Timer(OnTimerElapsed, null, TimeSpan.Zero, TimeSpan.FromSeconds(10));

    // Wait if someone tells us to die or do every five seconds something else.
    do
    {
        signaled = waitHandle.WaitOne(TimeSpan.FromSeconds(5));
        // ToDo: Something else if desired.
    } while (!signaled);

    // The above loop with an interceptor could also be replaced by an endless waiter
    //waitHandle.WaitOne();

    Log("Got signal to kill myself.");
}

private static void Log(string message)
{
    Console.WriteLine(DateTime.Now + ": " + message);
}

private static void OnTimerElapsed(object state)
{
    Log("Timer elapsed.");
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一个比这个线程中的大多数答案要好得多的答案,我使用`while(true)`样式循环从大约30%的CPU使用率到使用WaitHandle平均~0.04%的CPU使用率. (3认同)

sll*_*sll 9

您可以使用System.Threading.Timer类,它提供在给定时间段内异步执行回调的功能.

public Timer(
    TimerCallback callback,
    Object state,
    int dueTime,
    int period
)
Run Code Online (Sandbox Code Playgroud)

作为替代方案,存在System.Timers.Timer类,其暴露经历的事件,该事件在给定的时间段过去时上升.

  • 时间的最小分辨率为30毫秒 - 这对他来说可能是也可能不是问题; 至少在你的答案中表明它. (2认同)
  • 是的,但为什么30ms而不是〜15ms?有没有提到MSDN? (2认同)