Arm Mbed OS support forum

How to Dispatch EventQueues on Multiple Threads?

I want to dispatch two different eventqueue on two threads so that I can modify their priorities. They should toggle two led at different frequencies. However, only one of them would turn on. It seems that the OS never switches task even if I use ThisThread::yield(); . What am I missing here? Thanks in advance.

#include "mbed.h"      
#define TASK1_FLAG 10
#define DELAY 5ms
#define MS_100 100
#define TASK2_FLAG 10
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);
DigitalOut led1(LED1);

void Task1();
void Task2();
void Task3();
void Task4();

int main(void)
{
    Thread t1;
    Thread t2;
    
    EventQueue queue1(32*EVENTS_EVENT_SIZE);
    EventQueue queue2(32*EVENTS_EVENT_SIZE);
 

    t1.start(callback(&queue1, &EventQueue::dispatch_forever));
    queue1.call_every(1s,&Task1);  
    queue1.dispatch_forever();   
    
    t2.start(callback(&queue2, &EventQueue::dispatch_forever));
    queue2.call_every(2s,&Task2);  
    queue2.dispatch_forever();

    
   return 0;
}

void Task1()
{
 

        led1=1;
        ThisThread::sleep_for(5ms);
        led1=0;
        ThisThread::yield(); 
}

void Task2()
{
       led2 = 1;
       ThisThread::sleep_for(5ms);
       led2 = 0;
       ThisThread::yield();
}

Hello,

just try cutout queueX.dispatch_forever(); from your code, because you already do it in thread.start(...) and also you need to add while(1); to the end of main.

BR, Jan

1 Like

The LEDs wouldn’t turn on if I get rid of the dispatch_forever(); after calling queueX.call_every(); I tried to to modify it to the following code and lights are flashing but if change both queue1 and queue 2 to dispatch_once(); neither of the LEDs will turn on. I am not sure why.

Why do I need a while(1) inside of my main? Thank you!

    t1.start(callback(&queue1, &EventQueue::dispatch_forever));
    queue1.call_every(1s,&Task1);  
//    queue1.dispatch_forever();   
    queue1.dispatch_once();  
    
    t2.start(callback(&queue2, &EventQueue::dispatch_forever));
    queue2.call_every(2s,&Task2);  
    queue2.dispatch_forever();

You not need it, the associated thread do it for you. If you want to dispatch them by yourself then do not use threads. Check docs and examples of EventQueue - API references and tutorials | Mbed OS 6 Documentation

Without a while() at the end of the main, the program will leave the main and then the program ends.

BR, Jan

Why do I need a while(1) inside of my main? Thank you!

Without that the main thread is terminated and goes out the scope. This results in deleting of all the variables declared/defined in it’s scope (i.e. t1, t2, queue1 and queue2).
If you declare/define them as global then the program should work without having an endless while loop inside the main function:

#include "mbed.h"

#define TASK1_FLAG  10
#define DELAY       5ms
#define MS_100      100
#define TASK2_FLAG  10

DigitalOut  led2(LED2);
DigitalOut  led3(LED3);
DigitalOut  led4(LED4);
DigitalOut  led1(LED1);

void        Task1();
void        Task2();
void        Task3();
void        Task4();

Thread      t1;
Thread      t2;

EventQueue  queue1(32 * EVENTS_EVENT_SIZE);
EventQueue  queue2(32 * EVENTS_EVENT_SIZE);

int main(void)
{
    t1.start(callback(&queue1, &EventQueue::dispatch_forever));
    queue1.call_every(1s, & Task1);

    t2.start(callback(&queue2, &EventQueue::dispatch_forever));
    queue2.call_every(2s, & Task2);

    //    while(1);
}

void Task1()
{
    led1 = 1;
    ThisThread::sleep_for(5ms);
    led1 = 0;
    ThisThread::yield();
}

void Task2()
{
    led2 = 1;
    ThisThread::sleep_for(5ms);
    led2 = 0;
    ThisThread::yield();
}
1 Like

Thank you so much!! I never thought that the problem was my main thread terminated. It all makes sense now!

Thank you!! It is now working :slight_smile: