c++ - ESP32:异步倒数
问题描述
我编写了一个从 5 倒数到 0 的小程序,然后执行 println。我已经包装了一点,但请让我展示我的代码:
主程序
#include "MyObject.h"
#include <string>
using namespace std;
MyObjekt *myObject;
void setup() {
Serial.begin(115200);
string trigger = "triggering";
myObject = new MyObject(trigger);
}
void loop(){}
我的对象.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <string>
using namespace std;
class MyObject{
public:
string field;
MyObject(string trigger);
string GetField(){ return field; }
void SetField(string trigger);
};
#endif
我的对象.cpp
#include "MyObject.h"
#include <string>
using namespace std;
#include "Timer.h"
MyObject::MyObject(string trigger){
SetField(trigger);
}
void MyObject::SetField(string trigger){
field = trigger;
auto f = []() {std::cout << "---------------- I waited to print! ----------------\n"; };
Timer t1{10000,f};
}
定时器.h
#include <iostream>
#include <chrono>
#include <thread>
#include <functional>
#include <mutex>
#include <condition_variable>
class Timer {
public:
Timer(size_t time, const std::function<void(void)>& f) : time{std::chrono::milliseconds{time}}, f{f} {}
~Timer() {wait_thread.join();}
private:
void wait_then_call()
{
std::unique_lock<std::mutex> lck{mtx};
for(int i{5}; i > 0; --i) {
//std::cout << "Thread " << wait_thread.get_id() << " countdown at: " << '\t' << i << '\n';
cv.wait_for(lck, time / 10);
}
f();
}
std::mutex mtx;
std::condition_variable cv{};
std::chrono::milliseconds time;
std::function <void(void)> f;
std::thread wait_thread{[this]() {wait_then_call();}};
};
不幸的是,这阻塞了主线程,因此在此期间没有做任何其他事情(如另一个 println)。是否有可能在后台执行此倒计时并且仅f
在前台执行 println ( )(换句话说:在工作时进行侦听,如果检测到后台 println 并将其发送给侦听器,则执行,然后再次侦听并继续工作)?
对每一个答案和帮助工作都会感到非常高兴。对不起,如果我表达自己的问题,我希望它变得清楚我想要实现的目标^^
此致
解决方案
首先,new
如果你从不调用delete
,不要使用关键字,因为它会导致内存泄漏。你想要什么可以通过两种方式实现:
1.使用计数器
这仍然在 loopTask 上运行,但它让其他代码运行。
long lastMillis = 0;
long interval = 1000;
long counter = 5;
void setup() {
Serial.begin(115200);
}
void loop() {
if (millis() - lastMillis > interval && counter >= 0) {
lastMillis = millis();
Serial.println(counter--);
}
//Other code would still run
}
2.创建另一个任务
这将是完全异步的,即使您在另一个任务上调用 delay(),loopTask 上的代码仍然会运行。
int counter = 5;
int interval = 1000;
void vTask(void *param) {
while (counter >= 0) {
delay(1000);
Serial.println(counter--);
}
vTaskDelete(NULL);
}
void setup() {
Serial.begin(115200);
xTaskCreate(vTask, "vTask", 4096, NULL, 1, NULL);
}
void loop() {}
推荐阅读
- c# - 使用 Hololens 2 在空间映射网格上生成对象
- python - Numba CUDA:更改 xr.DataArray 形状会导致`调用 cuMemcpyDtoH 导致 UNKNOWN_CUDA_ERROR`
- arrays - 访问在 React Native 中设置为变量的其他对象中的对象
- c - 重新启动客户端-服务器应用程序时如何解决“地址已在使用中”?
- java - EL1021E: 尝试访问属性时出现问题
- python - 如何根据python数据框中的2个以上复杂条件计算特定列的总和
- c# - EntityFramework 6.4.4 和 SQL 聚合具有多个参数的用户定义函数
- r - 重命名列表而不覆盖 R 中的数据
- linux - Azure:如何在部署过程中运行命令?
- azure-data-factory-2 - 在 Azure 数据工厂(派生列)中创建 GUID