虽然我使用的是Arduino IDE,但运行代码的设备是ESP8266。
我确信我的代码结构错误,但我不确定最好的方法,希望有人可以指出我正确的方向。
要简化方案,我需要一个基本的例子:
我的main loop()函数在每次传递时只运行一个callback()函数(PubSubClient MQTT)。这个回调函数首先将一个全局布尔变量“run”设置为false,然后执行以下三项操作之一:
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()循环,该循环将中断,整个过程将返回循环()。
但是如果action1()正在运行并且callback()收到启动action2()的命令,则action2()将启动,而action1()只是暂停等待返回。
我认为因此在action1()和action2()之间来回轻拂可能会导致内存问题,因为循环堆叠在一起。如果我这么做的话,我看到设备崩溃了。
我想也许callback()需要'queue'action1()或action2()然后让main loop()运行它们?这样我们总是会回到主循环(),从而结束所有其他循环。我确信有更好的解决方案。
答案 0 :(得分:2)
您的代码结构确实不正确:
run
变量使callback()
不可重入,这可能会导致处理过早结束。 事实上,你最好选择一个事件循环,就像你已经在队列中指出的一样:
callback()
,它会将项目排队并返回。 不清楚主循环是否会永远运行,或者只是在收到某些特殊输入之前,或者直到队列为空。由您决定。
我不知道你的回调是如何在arduino模型中触发的。但是如果它中断了正在运行的进程,你还需要确保队列中没有竞争条件,例如使用锁。
答案 1 :(得分:0)
虽然循环通常是一个糟糕的设计。你应该使用loop()函数。
重新记录上次收到的有效命令并重复调用相应的action_x()
。这个功能"做了一些事情"并且返回得非常快,因此您不需要callback()
。
如果action_x()
返回状态以表示已完成任务,通常会很方便。