ESP-IDF 如何检查任务是否已经 运行?
ESP-IDF How to ckeck if task is already running?
我有一份工作应该 运行 最短间隔为 5 秒。启动此作业的触发器可以在任何时刻以任何频率执行。
在 RTOS 环境中解决这种情况的最佳方法是什么?
我想创建一个函数,如果任务不存在则创建一个任务。现有任务应等待最小间隔过去后再做任何事情。在等待时,应该创建它的函数应该跳过新任务的创建。
检查任务是否已创建但尚未完成的正确方法是什么?
在这种情况下我是否应该使用任务?
下面的代码示例:
#define CONFIG_MIN_INTERVAL 5000
uint32_t last_execution_timestamp = 0;
TaskHandle_t *task_handle = NULL;
bool task_done = true;
static void report_task(void *context)
{
if (esp_timer_get_time() / 1000 < last_execution_timestamp + CONFIG_MIN_INTERVAL)
{
ESP_LOGI(stateTAG, "need to wait for for right time");
int time_to_wait = last_execution_timestamp + CONFIG_MIN_INTERVAL - esp_timer_get_time() / 1000;
vTaskDelay(time_to_wait / portTICK_PERIOD_MS);
}
// do something...
task_done = true;
vTaskDelete(task_handle);
}
void init_report_task(uint32_t context)
{
if (!task_done)
{
ESP_LOGI(stateTAG, "TASK already exists");
}
else
{
ESP_LOGI(stateTAG, "Creating task");
xTaskCreate(&report_task, "report_task", 8192, (void *)context, 4, task_handle);
task_done = false;
}
}
eTaskGetState 可用于检查任务是否已经 运行ning,但这种解决方案容易受到竞争的影响。例如,您的任务在技术上仍然是“运行ning”,而实际上它正在“完成”,即设置 task_done = true;
并准备退出。
更好的解决方案可能是使用 queue (or a semaphore) 并让任务 运行 持续运行,等待消息到达并循环处理它们。
使用 semaphore,您可以 xSemaphoreTake(sem, 5000 / portTICK_PERIOD_MS);
等待唤醒条件或 5 秒超时,以先到者为准。
== 编辑 ==
if there is no events task should wait. Only if event happens it should run the job. It should run it immediately if there was no execution in past 5 seconds. If there was an execution it should wait until 5 seconds since last execution and only then run it
您可以通过仔细管理信号量的滴答等待来实现。像这样的东西(未经测试):
TickType_t nextDelay = portMAX_DELAY;
TickType_t lastWakeup = 0;
const TickType_t minDelay = 5000 / portTICK_PERIOD_MS;
for (;;) {
bool signalled = xSemaphoreTake(sem, nextDelay);
TickType_t now = (TickType_t)(esp_timer_get_time() / (portTICK_PERIOD_MS * 1000));
if (signalled) {
TickType_t ticksSinceLastWakeup = now - lastWakeup;
if (ticksSinceLastWakeup < minDelay) {
// wakeup too soon - schedule next wakeup and go back to sleep
nextDelay = minDelay - ticksSinceLastWakeup;
continue;
}
}
lastWakeup = now;
nextDelay = portMAX_DELAY;
// do work ...
}
我有一份工作应该 运行 最短间隔为 5 秒。启动此作业的触发器可以在任何时刻以任何频率执行。
在 RTOS 环境中解决这种情况的最佳方法是什么?
我想创建一个函数,如果任务不存在则创建一个任务。现有任务应等待最小间隔过去后再做任何事情。在等待时,应该创建它的函数应该跳过新任务的创建。
检查任务是否已创建但尚未完成的正确方法是什么? 在这种情况下我是否应该使用任务?
下面的代码示例:
#define CONFIG_MIN_INTERVAL 5000
uint32_t last_execution_timestamp = 0;
TaskHandle_t *task_handle = NULL;
bool task_done = true;
static void report_task(void *context)
{
if (esp_timer_get_time() / 1000 < last_execution_timestamp + CONFIG_MIN_INTERVAL)
{
ESP_LOGI(stateTAG, "need to wait for for right time");
int time_to_wait = last_execution_timestamp + CONFIG_MIN_INTERVAL - esp_timer_get_time() / 1000;
vTaskDelay(time_to_wait / portTICK_PERIOD_MS);
}
// do something...
task_done = true;
vTaskDelete(task_handle);
}
void init_report_task(uint32_t context)
{
if (!task_done)
{
ESP_LOGI(stateTAG, "TASK already exists");
}
else
{
ESP_LOGI(stateTAG, "Creating task");
xTaskCreate(&report_task, "report_task", 8192, (void *)context, 4, task_handle);
task_done = false;
}
}
eTaskGetState 可用于检查任务是否已经 运行ning,但这种解决方案容易受到竞争的影响。例如,您的任务在技术上仍然是“运行ning”,而实际上它正在“完成”,即设置 task_done = true;
并准备退出。
更好的解决方案可能是使用 queue (or a semaphore) 并让任务 运行 持续运行,等待消息到达并循环处理它们。
使用 semaphore,您可以 xSemaphoreTake(sem, 5000 / portTICK_PERIOD_MS);
等待唤醒条件或 5 秒超时,以先到者为准。
== 编辑 ==
if there is no events task should wait. Only if event happens it should run the job. It should run it immediately if there was no execution in past 5 seconds. If there was an execution it should wait until 5 seconds since last execution and only then run it
您可以通过仔细管理信号量的滴答等待来实现。像这样的东西(未经测试):
TickType_t nextDelay = portMAX_DELAY;
TickType_t lastWakeup = 0;
const TickType_t minDelay = 5000 / portTICK_PERIOD_MS;
for (;;) {
bool signalled = xSemaphoreTake(sem, nextDelay);
TickType_t now = (TickType_t)(esp_timer_get_time() / (portTICK_PERIOD_MS * 1000));
if (signalled) {
TickType_t ticksSinceLastWakeup = now - lastWakeup;
if (ticksSinceLastWakeup < minDelay) {
// wakeup too soon - schedule next wakeup and go back to sleep
nextDelay = minDelay - ticksSinceLastWakeup;
continue;
}
}
lastWakeup = now;
nextDelay = portMAX_DELAY;
// do work ...
}