c# ESP 32/FreeRTOS,如何在触发新任务时停止当前运行的任务(避免重叠)

l5tcr1uw  于 2023-01-15  发布在  C#
关注(0)|答案(3)|浏览(373)

我的工作代码,以控制2模块继电器有关门的访问。我正在寻找停止当前运行的任务的方法,在运行新的(相同的任务)。所有我想要的是避免重叠。

void TaskOpenManRoom(void *parameter){
  Serial.println("Opening men room");
  digitalWrite(manRelay, LOW);
  vTaskDelay(6000 / portTICK_PERIOD_MS);
  digitalWrite(manRelay, HIGH);
  Serial.println("Closing men room");
  vTaskDelete(NULL);
};

xTaskCreate(
      TaskOpenManRoom,
      "TaskOpenManRoom",
      1000,
      (void *) &man,
      1,
      &TaskMen
    );

我的目标是延长门应该打开的时间。所以基本上当第一个任务被触发,然后过了一段时间第二个任务,门应该保持打开另一个6000毫秒。
在当前代码中,当第二个任务像在第一个任务中间一样被调用时,由于第一个任务调用digitalWrite(manRelay, HIGH);,门被关闭
如果你能提示我如何在第二个任务被触发时杀死第一个任务,我将非常感激。

ix0qys7i

ix0qys7i1#

任务应该是长期运行的,因为它们是相对重量级的。不要为每个用户活动启动和结束任务,也不要长时间延迟它们。
您的功能完全不需要任何任务,只需要一个timer在6000 ms后执行关闭活动。然后,您可以随时重置它。

TimerHandle_t closeManRoomTimer;

void OpenManRoom() {
  xTimerReset(closeManRoomTimer, 100);    // <------ (re)arm the close timer
  Serial.println("Opening men room");
  digitalWrite(manRelay, LOW);
};

void CloseManRoom(TimerHandle_t) {
  Serial.println("Closing men room");
  digitalWrite(manRelay, HIGH);
};

// during program startup, setup a one-shot close timer
closeManRoomTimer = xTimerCreate("closeManRoomTimer", pdMS_TO_TICKS(6000), pdFALSE, 0, &CloseManRoom);
wfypjpf4

wfypjpf42#

我不会在第二个任务开始的时候扼杀第一个任务。
如果你使用一个任务,我会把它重写成大致如下的形式:

cast parameter to pointer to uint32
atomic increment open count, and if it was zero {
    open the door
    repeat {
        sleep six seconds
    } atomic decrement count, and exit loop if it was 1
    close the door
}
exit the task

...并且在创建任务时,传递一个指向uint32_t的指针,以便它用来存储打开计数。
因此,任务开始时自动递增打开计数,它返回打开计数中 * previous * 的值,如果该值为零,则表示门当前关闭,在这种情况下,我们打开门并进入睡眠状态。
如果任务在休眠状态下再次运行,打开计数将变为1,我们立即将其递增,但当我们检查前一个值时,它是1,因此我们不再尝试再次打开门--我们只是跳过if语句中的所有内容,并退出任务。
当任务的第一个示例醒来时,它会递减计数,如果计数为1,它就会退出循环,关上门,然后退出任务;但如果任务在休眠时再次运行,计数仍将大于1,因此它将留在循环中,并休眠更多时间。
这是开放的一点点优化。因为它现在的立场,它休眠一个固定的时间段(6秒)。如果任务足够昂贵而需要一点额外的工作,则我们可以进行原子交换,以检索当前打开计数并将打开计数设置为0,将检索到的值乘以6000,然后睡那么长时间。这增加了相当多的额外复杂性,在这种情况下,好处将太小,不能证明它的合理性。
这取决于我们在门打开时运行任务的次数不超过40亿次。如果我们这样做,原子增量将溢出,代码将出现错误。(和大多数其他人)这不太可能成为问题。在可能成为问题的罕见情况下,显而易见解决办法是使用64位变量(以及64位原子递增和递减)。递增变量直到64位变量溢出通常是不现实的(例如,如果以1 GHz递增,则需要几个世纪)。

ou6hu8tu

ou6hu8tu3#

多种方式:
1.使用vTaskDelay将任务置于非运行状态(不阻塞
1.等待、互斥信号量、队列或来自另一个任务的任务通知。
如果你能提示我如何在第二个任务被触发时杀死第一个任务,我将非常感激。
它将终止当前任务:

vTaskDelete(NULL);

相关问题