簡體   English   中英

用回調函數中斷while循環的最佳方法是什么?

[英]What is the best way to break a while loop with a callback function?

雖然我使用的是Arduino IDE,但運行代碼的設備是ESP8266。

我確定我的代碼結構錯誤,但是我不確定最好的方法,希望有人可以指出正確的方向。

歸結為一個基本的例子:

我的main loop()函數在每次傳遞時僅運行一個callback()函數(PubSubClient MQTT)。 此回調函數首先將全局布爾變量“ run”設置為false,然后執行3件事之一:

  1. 如果收到“ 1”,它將運行一個名為action1()的函數。
  2. 如果收到“ 2”,它將運行一個名為action2()的函數。
  3. 如果接收到“ 3”,它將打印一行到“ Serial”。
  4. 如果有其他任何事情或什么也沒收到,它將什么都不做。

action1()和action2()函數都是看起來像這樣的循環:

void action1() {
  run = true;             // Do this once to start the loop
  while (run == true) {
    // Do some stuff
    callback();           // To check for new messages
  }
}

這是問題所在:

如果action1()正在運行,並且callback()接收到“ 3”,則一切正常。 回調會將“ run”變量設置為false,將行打印到Serial,然后返回到action1()循環,該循環將中斷,整個過程返回loop()。

但是,如果action1()正在運行,並且callback()接收到用於啟動action2()的命令,則action2()將啟動,並且action1()只是暫停以等待返回。

我認為因此在action1()和action2()之間來回輕拂可能會導致內存問題,因為循環彼此重疊。 如果執行此操作,我會看到設備崩潰。

我想也許callback()需要“排隊” action1()或action2(),然后讓main loop()運行它們? 這樣,我們將始終返回到main loop(),從而結束所有其他循環。 我相信有更好的解決方案。

您的代碼結構確實不正確:

  • 回調的調用將堆積起來。 如果您有許多回調事件,則可能會導致堆棧溢出。
  • 使用全局run變量會使callback()不可重入,這可能導致處理過早結束。

實際上,您最好選擇一個事件循環,正如您已經在隊列中指出的那樣:

  • 僅當收到ai item item時,才會調用callback()並且該方法將使item排隊並返回。
  • 您的主循環將在每次迭代時僅從隊列中讀取某些內容(如果有的話),然后調用正確的操作。
  • 如有必要,您也可以調用某些輪詢功能(如果需要)。
  • 如有必要,您還可以調用輸出函數以反映當前狀態。

目前尚不清楚主循環是否將永遠運行,或者僅在接收到一些特殊輸入之前運行,還是直到隊列為空。 由您決定。

我不知道在arduino模型中如何觸發您的回調。 但是,如果它中斷了正在運行的進程,則還需要確保隊列上沒有競爭條件,例如帶鎖。

而循環通常是一個不好的設計。 這里有loop()函數,您應該使用它。

記住最后收到的有效命令,並重復調用相應的action_x() 該函數“做一些事情”並返回非常快,因此您不需要該callback()

如果action_x()返回一個狀態以表示已完成任務,通常會很方便。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM