Зацикливание программы. Является ли вызов модуля внутри себя плохой идеей? - PullRequest
3 голосов
/ 15 февраля 2012

У меня есть программа, которую я хочу, чтобы постоянно работал.То, как я сейчас его кодирую, как только оно достигает конца своей функции, оно вызывает себя;на самом деле он никогда не достигает своей конечной строки.

Sub run

    *Run all code here*

    Call run

End Sub

Были подняты вопросы по этому поводу, обеспокоенность в том, что у программы никогда не будет шанса "вытолкнуть" все, что было "надето" на нее.По сути, через определенный промежуток времени постоянный самозвонок перегружает процессор.Вместо этого был предложен альтернативный цикл while, который никогда не заканчивается, по сути,

Sub run

While program_run = true then

    *Run all code here* 

Loop

End Sub

И просто никогда не делать program_run = false.

  1. Я сформулировалколичество вещей в "layman-y", потому что я не уверен в правильности технических терминов.

  2. Я знаком с терминами "pop" и "push" вконтекст списков и структур данных, но только на базовом уровне;Я не думаю, что эти конкретные термины применимы к этой ситуации, но именно так она была сформулирована для меня.(Программа загружает .csv и выполняет множество операций с данными, т.е. форматирование, копирование / вставка, загрузка в MySQL и т. Д.)

  3. Это также связано с тем, чтобыаппаратное обеспечение не перегружается постоянно, поэтому, если это более уместно в SuperUser, я понимаю.

Вопросы:

  1. Это проблемапрограмма / аппаратная часть будет «перегружена» законной?

  2. Есть ли практическая разница между модулем самозвонка и циклом while, который никогда не заканчивается?

Заранее благодарю за любую помощь!

Ответы [ 2 ]

4 голосов
/ 16 февраля 2012

1. Является ли опасение, что программа / оборудование будет «перегружено» законным?

Зависит от того, что вы подразумеваете под "перегружен". В зависимости от вашего точного кода это может привести к тому, что один процессор будет работать непрерывно и, следовательно, нагреваться. Но компьютеры обычно рассчитаны на то, чтобы справляться с этим, и это не должно вызывать проблем, если вы не препятствуете их вентиляции. Это может разрядить аккумулятор ноутбука довольно быстро. Все это действительно зависит от того, что именно делает ваш код.

Что касается "перегрузки программы", я не знаю, что это значит, но это приятно приводит к вашему второму вопросу:

2. Есть ли практическая разница между модулем самозвонка и циклом while, который никогда не заканчивается?

Да, есть разница. Поскольку вы спрашиваете об этом на stackoverflow.com, вам будет интересно узнать, что ваш первый бит кода (процедура, вызывающая сам себя) буквально приведет к переполнению стека . Вы не «перегружаете процессор», вы исчерпываете память, доступную в стеке вызовов. Этот объем памяти не бесконечен, но чуть больше его занимает каждый раз, когда вы вызываете вашу run процедуру бесконечное число раз, так что да, в какой-то момент вы исчерпываете и получаете переполнение стека.

Что касается вашего второго бита кода, он не скомпилируется. (While ... Then ... Loop не существует в VBA. Вы смешиваете три разных типа синтаксиса.)

Если вы абсолютно уверены, что хотите, чтобы ваша программа работала до конца времени (в том, что касается вашего компьютера), то вы можете сделать бесконечный цикл, подобный этому:

Sub run()
    Do
        '*Run all code here*
    Loop
End Sub

Однако вряд ли вы действительно хотите, чтобы ваш код работал до конца времени. Я спрашивал себя, каково будет правдоподобное конечное условие, и выполнял бы его.

Sub run()
    Dim endConditionReached As Boolean
    endConditionReached = False
    Do While Not endConditionReached 
        '*Run all code here*
        ' code sets endConditionReached to True when appropriate
    Loop
End Sub
3 голосов
/ 16 февраля 2012

Если вы используете функцию с автоматическим вызовом, каждый раз, когда она вызывает себя, в стек добавляется новая функция. Простой способ проверить это - запустить приведенный ниже код в режиме отладки (F8) и после нескольких вызовов проверить стек (View / Stack или CTRL + L): вы увидите, что в стеке есть несколько вызовов процедуры.

Sub test()

  test

End Sub

Если вы просто запустите этот код (F5), вы получите сообщение об ошибке «недостаточно места в стеке» довольно быстро (через секунду или 2 на моем компьютере).

Если вы используете бесконечный цикл, предполагая, что в вашем цикле нет утечек памяти, у вас не должно быть проблем с переполнением. Но это не очень чисто, так как вам нужно «убить» процедуру, чтобы остановить ее.

Альтернативой (в зависимости от того, чего вы пытаетесь добиться) было бы иметь своего рода планировщик, который запускает ваш цикл каждые x секунд и может быть остановлен по требованию.

...