Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How can I queue a function to be executed in the main thread with as high priority as possible?



  • I would like to be able to have another thread queue a std::function to be executed in my application's main thread with as high a priority as possible, meaning that executing this function takes precedence over anything else that is happening in the main thread, save for any task the main thread is currently executing. (To clarify, the currently executing task in the main thread doesn't need to yield execution or anything like that. This queued function should simply be the very next event that the thread processes with as little delay as possible.)

    There are a number of ways a thread can set up a function to be called in another specific QThread, such as using a single shot QTimer with a zero second interval, or using QMetaObject::invokeMethod. But I'm not sure how execution of the function will be prioritized in relation to other tasks that are being processed by the main thread.

    The first thought I had was to create a custom QEvent that contains an instance of the function I want to execute, subclass QApplication and override its event() method so that it properly handles this new custom event by executing the function, and then post it using something like:

    qApp->postEvent(qApp, customEvent, Qt::HighEventPriority * 1000000);
    

    ...or using some other suitable huge integer for the event priority. But having to subclass QApplication strikes me as clunky, and I'm not even sure if this is the best way to go about doing this since I don't have deep knowledge of how Qt's event system works. (Like how would this be prioritized in relation to events dispatched to other QObject's whose thread affinity is also set to the main thread?)

    Is there a better method?


  • Moderators

    @Guy-Gizmo said in How can I queue a function to be executed in the main thread with as high priority as possible?:

    The first thought I had was to create a custom QEvent that contains an instance of the function I want to execute, subclass QApplication and override its event() method so that it properly handles this new custom event by executing the function, and then post it using something like:

    qApp->postEvent(qApp, customEvent, Qt::HighEventPriority * 1000000);
    

    ...or using some other suitable huge integer for the event priority.

    Yep, that's a good way to achieve what you want.

    But having to subclass QApplication strikes me as clunky

    You don't have to subclass QApplication. You can install an event filter instead: https://doc.qt.io/qt-5/qobject.html#installEventFilter

    I'm not sure how execution of the function will be prioritized in relation to other tasks that are being processed by the main thread.

    https://doc.qt.io/qt-5/qcoreapplication.html#postEvent says:

    "Events are sorted in descending priority order, i.e. events with a high priority are queued before events with a lower priority.... Events with equal priority will be processed in the order posted."

    how would this be prioritized in relation to events dispatched to other QObject's whose thread affinity is also set to the main thread?

    All QObjects that live in the same thread will share the same event queue. By default, all the events have the same priority, so the events will be dispatched in the order of arrival from the other threads.

    If you set a higher priority on your event, yours will be put at the front of the queue, which sounds like what you want.

    Note: Queuing and priority only apply to queued signals/events. Signals that are emitted from other threads get converted into events and join the event queue. However, if a signal is emitted from the main thread and the receiver also lives in the main thread, then it doesn't get converted into an event and it doesn't go through the event queue. Instead, it will be treated like a direct function call -- the function that emits the signal will be blocked as soon as the signal is emitted, and only continue when all connected slots that live in the same thread have finished running.



  • @JKSH You know, even though I use event filters all the time, for some reason I didn't think about using them here. But obviously that's a better way of accomplishing this than subclassing QApplication. And based on the doc excerpt you posted, it sounds like posting an event with very high priority is what I want.


Log in to reply