ESP8266Scheduler
ESP8266Scheduler copied to clipboard
Example using delay or yield in class instantiated in task
It would be great if you can add an example on how to use a non blocking delay in a other class than the Task itself.
I am now doing it like the example below (based on the Simple.ino example), but it requires changing the scheduler to make delay & yield public
class PrintManager {
protected:
Task* _task;
public:
PrintManager(Task* task) {
_task = task;
}
void print() {
Serial.println("Print Loop Start");
_task->delay(4000);
Serial.println("Print Loop End");
_task->delay(4000);
}
};
class PrintTask : public Task {
public:
PrintTask() : Task(), printManager((Task *) this){};
protected:
PrintManager printManager;
void loop() {
printManager.print();
}
} print_task;
Thanks!
Hi,
This is not something I have ever thought of doing. Off the top of my head, I would probably pass the delay function through as a param, rather than the task, would this work for you?
Hi, I am currently using with a modified version of NTPclient to do a non-blocking wait for an update from a NTP server, but I expect there are many more libraries that have internal delays that I may want to make non-blocking in the future
What would passing the function look like? It should still set delay_time and delay_ms of the task in order to have shouldRun run correctly, right?
ps. By the way, thanks for the library!
Hi,
It would look something like this:
typedef void (*delayFunc)(unsigned long ms);
class PrintManager {
protected:
delayFunc _delay;
public:
PrintManager(delayFunc delay) {
_delay = delay;
}
void print() {
Serial.println("Print Loop Start");
_delay(4000);
Serial.println("Print Loop End");
_delay(4000);
}
};
class PrintTask : public Task {
public:
PrintTask() : Task(), printManager(this->delay){};
protected:
PrintManager printManager;
void loop() {
printManager.print();
}
} print_task;
I havnt tried the code, but it is around there somewhere.
Thanks, I will try it out!
I tried another approach which would not require passing a function or object:
I added the static function
void SchedulerClass::delay(unsigned long ms) {
current->delay(ms);
}
to Scheduler. My thinking was that I could then call it the Non-Task object (e.g. PrintManager) as
Scheduler.Delay(4000)
or
SchedulerClass::Delay(4000)
Which would then call the Delay function in the Task that is currently running
However, this gives a niece big crash as soon as current->delay calls the underlying cont_yield(&context); in Task class.
Do you have any idea why? I am afraid that I do not understand the mechanics deeply enough to see why this fails.
It entirely depends on how this is done. It would be very difficult to say without being able to map its exact flow.
I'd also like to call delay and yield without passing those functions all the way down. I just tried what @thijse proposes and it seems to work just fine.
However, this gives a niece big crash as soon as current->delay calls the underlying
cont_yield(&context);in Task class.
did you also happen to define yield as a class method?, if you did, make sure to also change yield(); to ::yield(); inside void SchedulerClass::begin() {}. Otherwise that yield refers to the class method, and then it crashes. See Qualified name lookup