【问题标题】:Is using multiple 'while()' loops bad practice?使用多个“while()”循环是不好的做法吗?
【发布时间】:2016-05-16 14:45:48
【问题描述】:

我正在编写两个相互配合的应用程序。一个是c++,另一个是C#。由于涉及流式数据,我在多个地方使用代码,例如:

while (true)
{
 //copy streamed data to other places

}

我注意到这些程序使用大量 cpu,并且响应速度变慢。使用这种循环是不好的编程吗?我应该添加一个:

Sleep(5);

在每个?这对 CPU 使用有帮助吗?

谢谢!

【问题讨论】:

  • 你的 cpu 有 100% 的使用率。用起来还不错。
  • @anti 这很好用,你还会看到一些人经常使用等效的for( ; ;)
  • while 循环不一定是不好的做法.. 你在其中放入的内容可以使它们如此
  • 如果有工作要做,就去做。如果您正在等待接收工作,请不要忙着等待。 (最好也不要轮询,使用等待新数据到来唤醒的函数)
  • 您应该研究异步,您可以将这些循环卸载到单独的线程中以避免响应问题。

标签: c# c++ while-loop cpu-usage


【解决方案1】:

一般来说,在代码中使用Thread.Sleep() 也会冻结线程,因此如果您担心的是响应性,则不应使用它。您应该考虑将流式处理方法移出主 (UI) 线程

另外,你提到它是一些流式处理,所以最佳实践不会像

while(!stream.EndOfStream)
{
//streaming
}

而是使用一些 DataReceived 事件(如果可用)

【讨论】:

  • 谢谢,我会调查的。
【解决方案2】:

你可能会发现代码更多的是格式

while (true)
{
   //WAIT for streamed data to arrive
   //READ data from stream
   //COPY streamed data to other places

   //BREAK when no more data/program is ending


}

这是完全正常的。另一个常见的解决方案是

while (boolean_variable_if_program_is_to_keep_running)
{
   //WAIT for streamed data to arrive
   //READ data from stream
   //COPY streamed data to other places

   //when no more data/program is ending
   //   set boolean_variable_if_program_is_to_keep_running = FALSE


}

【讨论】:

    【解决方案3】:

    您真正需要避免的(为了您的 CPU 的健康)是让您的程序在不使用系统线程等待函数的情况下在 while(true) 循环中等待数据。

    示例 1:

    while(true) {
       if (thereIsSomeDataToStream) {
           StreamDataFunction();
       }
    }
    

    在这个例子中,如果thereIsSomeDataToStream 暂时为假,那么即使没有数据流,CPU 仍将继续 100% 工作,执行while 循环。所以这会浪费 CPU 并导致您的计算机变慢。

    示例 2:

    while(true) {
       if (thereIsSomeDataToStream) {
           StreamDataFunction();
       }
       else {
           SystemThreadingWaitFunction();
       }
    }
    

    相反,在这个例子中,当没有更多数据流时,线程会停止一段时间。操作系统将利用这段空闲时间来执行其他线程,一段时间后,系统将唤醒您的线程,该线程将恢复并再次循环以流式传输可能的新数据。这样就不会浪费过多的 CPU,您的计算机将保持响应。

    要执行线程等待过程,您可能有几种可能性:

    • 首先,您可以按照您的建议使用Sleep(t)。这可能会 作业:编译器提供的睡眠函数在逻辑上会使用 用于空闲当前线程的操作系统 API。但在这种情况下,你 将不得不等待所有指定的时间,即使一些数据来了 同时。所以如果等待时间太短,CPU就会过度工作,如果 时间太长,你的流媒体会滞后。

    • 或者你可以直接使用操作系统API,我会 推荐。如果您使用的是 Microsoft 环境,则有很多 您可以在此处记录的等待方法:Microsoft wait functions API。例如,您可以创建一个 Event 对象 将信号传入数据流。您可以发出此事件的信号 在您的代码或其他程序中的任何位置。在while 循环中,您 然后可以调用像WaitForSingleObject API 这样的函数,它会等待 信号状态的事件。以下是有关如何执行此操作的文档: Using event objects。我不了解linux或其他系统, 但我相信你可以在网上找到它。我自己做了几次, 编码并不难。享受 ! :)

    【讨论】:

      【解决方案4】:

      这是对我上面评论的扩展,但为了完整起见,我将在此处粘贴我在推荐中所写的内容(并添加到其中)。

      此类问题的一般解决方案是等待数据到达并在数据到达时对其进行处理(可能在您处理先前到达的数据时缓存新到达的数据)。至于实现的机制——嗯,这取决于一个具体的例子。例如,通常在图形处理应用程序(例如游戏)中,“游戏循环”本质上就是您所描述的(没有睡眠)。这在 GUI 应用程序设计中也会遇到。对于应用在处理之前等待事件的设计,请查看典型的网络客户端-服务器设计。

      至于CPU的减速,试试下面的代码观察明显减速:

      while(true);
      

      对比

      while(true) sleep(1);
      

      第一个变慢的原因是因为在每个循环中,CPU 都会检查循环中的条件是否计算为true(即,在本例中为true == true)。另一方面,在第二个示例中,CPU 检查是否为true == true,然后休眠1ms,这比检查true == true 所需的时间要长得多,从而腾出CPU 去做其他事情。

      现在,就您的示例而言,处理循环内的数据可能比检查true == true 花费更多的CPU 周期。因此,添加sleep 声明将无济于事,只会使情况恶化。

      您应该让内核来决定何时中断您的进程以将 CPU 周期专用于其他事情。

      当然,对我上面写的内容持保留态度(尤其是最后一段),因为它描绘了一张非常简单的图片,没有考虑到您的具体情况,这可能会受益于一种设计与另一种设计(我不不知道,因为你没有提供任何细节)。

      【讨论】:

        猜你喜欢
        • 2018-10-19
        • 2014-02-23
        • 2023-04-04
        • 2013-03-24
        • 1970-01-01
        • 1970-01-01
        • 2013-09-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多