[Interest] Expected event execution order in this, multi-thread application
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
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
More information about the Interest