[Interest] Expected event execution order in this, multi-thread application

Roland Hughes roland at logikalsolutions.com
Sun Sep 29 15:27:53 CEST 2019

On 9/29/19 5:00 AM, Richard Weickelt wrote:
> what is the expected event execution order in the following scenario?
> - 2 Threads running their event loop
> - Thread T1 is handling an event E1
> - Thread T2 sends an event E2 to T1 (queued)
> - Thread T1 (still handling E1) emits an event E3 to itself (direct) after
> E2 has already been enqueued.
> - E3 is a very long-running event. To prevent events from starving, T1 calls
> QCoreApplication::processEvents() periodically.
> Observed behaviour:
> - E3 gets immediately executed
> - E2 is executed after E3/E1 have completed
> Is this behavior expected? I would expected E2 being executed at least on
> the first invocation of QCoreApplication::processEvents(), but apparently it
> sits in the event queue until T1 returns from E3 (and also E1).
> In my scenario E2 is rather short and E3 expectes something from E2 in order
> to complete. So I run into a deadlock here.
> Would it be a solution to handle E3 in a queued connection? In case E2 is
> posted after E3 has started, would E2 be executed by processEvents()?

Non-queued connections are basically local function calls. You would 
have to force a queued connection, but you still could not reliably get 
your design to work. You have a sequential problem where steps must 
occur in a given order but may require differing amounts of time. In 
effect you are trying to do this without having a full Application 
Control Management System.


You really need to split this into restartable units of work and utilize 
an external queing agent.

This solution hasn't properly utilized stepwise refinement. T1 _cannot_ 
issue E3 until there is a pending E2, but it does, so this logic isn't 
properly broken down. Without knowing what your application is or 
anything more than these BASIC (the language, not a shout) variable 
names, here's the 5 minute architect job.

*) Forget events. Wrong tool for this job. Having said that, you are 
using Qt and probably unwilling to code the necessary architecture so we 
will attempt to make them work. You really should use a message queing 
system for this if not a full blown ACMS.

*)  T1  = your T1   T2 = your T2   T3 = Control Thread (possibly main 
event loop)

T1 chews on whatever it chews on. When it gets to the state of issuing 
the previous E3 it sends a T1-TASK-COMPLETE message to the control thread.

T2 chews on whatever it chews on. When it gets to the state of issuing 
the previous E3 it sends a T2-TASK-COMPLETE message to control thread.

T3 receives one or more TASK-COMPLETE messages and first records them 
into some form of data store. Then it checks via some kind of key/id or 
something if it has a matching T1-TASK-COMPLETE and T2-TASK-COMPLETE. If 
so, it combines whatever data is in the "complete" messages and launches 
what was previously E3, preferably in its own thread.

Each "task" must be designed so it can run flat out without dependencies 
from other tasks. Your control task, depending on the required 
granularity could even be split into CONTROL-STORE and CONTROL-DISPATCH 
with the dispatch portion being triggered each time a store completes to 
search for matching completed tasks so the next task can be launched.

If you don't have a hardware (serial port or some other kind of polling 
device) or database involved in T1 I would be very worried about having 
to call QCoreApplication::processEvents(). If one is doing database I/O 
in the main event loop you could easily need to do this for a large 
cursor of data, but you are in a thread or at least this description is.

Roland Hughes, President
Logikal Solutions


More information about the Interest mailing list