代码之家  ›  专栏  ›  技术社区  ›  Jeff Schumacher

对可怕的while(true)循环进行最佳重构

  •  13
  • Jeff Schumacher  · 技术社区  · 16 年前

    如果像我一样,你在一段时间(真的)的循环中颤抖,那么你也一定已经考虑了很久,也很难找到最好的方法来重构它。我见过几个不同的实现,没有一个比其他实现更好,例如计时器和委托组合。

    那么,您想出或看到的重构可怕的while(true)循环的最佳方法是什么呢?

    编辑 :正如一些评论所提到的,我的目的是让这个问题成为一个“无限循环”重构,例如运行一个Windows样式的服务,其中唯一的停止条件是OnStop或一个致命的异常。

    12 回复  |  直到 8 年前
        1
  •  22
  •   artur02    16 年前

    我们真的需要重构吗 虽然(真) 循环? 有时它是一种编码标准,大多数开发人员已经习惯了这种结构。如果您必须仔细考虑如何重构此代码,您确定重构它是一个好主意吗?

    古托 以前是编码标准中的败类。我见过算法 古托 使代码可读性大大提高,而且更短。有时不值得重构(或更好地使用 古托 )

    另一方面,你可以避免 虽然(真) 大部分时间。

        2
  •  58
  •   idmean    10 年前

    我的偏好是

    start:
    
       // code goes here
    
    goto start;
    

    这最清楚地表达了意图。祝你顺利通过编码标准。(想知道这会让我付出多少代价)。

        3
  •  22
  •   Konrad Rudolph    16 年前

    有什么可怕的?尝试找到一个常见的中断条件,并将其重构为循环的头部。如果不可能的话,那就好了。

        4
  •  13
  •   Jim Nelson    16 年前

    当我遇到一个while(true)循环时,它告诉我

    1. 在回路的顶部(或底部)不容易测试断裂条件,
      • 有多个中断条件,
      • 或者先前的程序员太懒了,无法正确地考虑循环。

    1和2意味着你可以坚持一段时间(对)。(我用 for(;;) 但在我看来,这是一个时尚的东西。)我有另一张海报,为什么害怕这个?我怕乌龟的环会跳到铁环上,“正确”地滚动。

        5
  •  12
  •   Jon B    16 年前

    将true替换为要用于中断循环的条件。

    对于服务或后台线程,可以使用:

    volatile bool m_shutdown = false;
    void Run()
    {
        while (!m_shutdown)
        { ... }
    }
    
        6
  •  11
  •   Ken Ray    16 年前

    为什么要重构?这个建筑有什么“可怕”的?它被广泛使用,并且被很好地理解。

    如果没坏,就别修了。

        7
  •  7
  •   S.Lott    16 年前

    “永远运行”的情况有时是大型状态机的一部分。许多嵌入式设备(带有“永远运行”循环)并不真正运行 永远 . 它们通常有几种操作模式,并将在这些模式之间排序。

    当我们建立热泵控制器时,有一个开机自检(post)模式运行了一段时间。然后有一个初步的环境收集模式运行,直到我们弄清楚所有的区域和恒温器以及其他什么。

    一些工程师声称接下来的就是“永远奔跑”的循环。其实没那么简单。实际上,是几个操作模式发生了翻转和翻滚。有暖气、除霜、制冷、空转等等。

    我的偏好是将“永远”循环视为真正的一种操作模式——在未来的某个时候可能会有其他的操作模式。

    someMode= True
    while someMode:
        try:
            ... do stuff ...
        except SomeException, e:
            log.exception( e )
            # will keep running
        except OtherException, e:
            log.info( "stopping now" )
            someMode= False
    

    在某些情况下,到目前为止我们还没有看到任何场景 someMode False . 但我喜欢假装在未来的版本中会有模式改变。

        8
  •  7
  •   Andrew Coleson    16 年前
    #define ever 1
    for (;ever;)
    

    ?

    嗯,别管它是什么样子,虽然(真的)可能和你要读的一样清楚。

        9
  •  3
  •   Keith Nicholas    16 年前

    呃,做一个重构……

    • 用无限递归替换无限循环:-)

    好吧,如果你有一种支持尾调用的语言……

        10
  •  3
  •   Grank    16 年前

    如果您希望它无限期地继续运行,直到程序流完全中止,那么while(true)没有任何问题。我最近在一个.NET数据收集服务中遇到了它,该服务将while(true)与thread.sleep结合在一起,每分钟唤醒一次,并向第三方数据服务轮询新报告。我考虑用一个计时器和一个委托来重构它,但最终决定这是最简单和最容易读取的方法。10次中有9次是清晰的代码味道,但当没有退出条件时,为什么会让事情变得更困难?

        11
  •  1
  •   Chris Cudmore    16 年前

    我不介意无限循环包含在一个窗口中,并随窗口一起消失。

    想想哈塞尔霍夫递归。

        12
  •  -2
  •   12431234123412341234123    8 年前
    void whiletrue_sim(void)
      {
        //some code
        whiletrue_sim();
      }
    

    警告:您的堆栈可能会溢出,这取决于语言、优化器和其他内容。