<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">Il giorno gio 1 lug 2021 alle ore 08:54 Giuseppe Corbelli <<a href="mailto:corbelligiuseppe@mesdan.it" target="_blank">corbelligiuseppe@mesdan.it</a>> ha scritto:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Well, since no synchronization is provided this is no surprise and holds <br>
true for everything that runs multithreaded.<br></blockquote><div><br></div><div>Yes, but since most people don't really understand how threading and UI work, it's still important to make this "higher level" point very clear. Event driven systems are so transparently used that users are often led to believe that different windows (or UI elements) can work independently, and can thus be created/accessed from other threads.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Very good point indeed. If you don't need an event loop (so no signals <br>
delivery) then there's no point in using QThread instead of plain <br>
threading module but you're absolutely right.<br></blockquote><div><br></div><div>Indeed, a QThread makes sense whenever any interaction with (and, most importantly, *to*) the UI is required. If we're not interested in the actual "output" of the thread to be in any way "notified" through the UI, a standard python thread will suffice.</div><div>The aspect of signal delivery depends on the direction: signals might still be required even without an event loop, but, still, an event loop is conceptually just something that runs (or "waits") until something happens: even a simple time.sleep() (without any while/for) can be considered as an event loop: it waits until the time has elapsed ;-)</div><div>An important aspect that should always be kept in mind and really helps the implementation is that a "worker" (or, better, "non-main") thread should usually be "self contained", and know nothing about the UI it is "working for". It is a compartmentalised object that should really work on its own, do its job, possibly wait for some input to do that job (but it doesn't need to know about the source of that input), and then tell the results of that job to "anything listening" to it, no matter what.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">> - for the same reason, it's not possible to connect the started signal <br>
> to a function of a QObject instance that exists in the main thread: it <br>
> would require moving the object to the thread, which is not allowed, and <br>
> the result is that the signal will be queued and then the function will <br>
> be executed in the receiver thread;<br>
<br>
I didn't understand this one. The started() signal of a QThread can be <br>
connected to a slot in any thread and the slot executed in the thread <br>
affine to the slot QObject.<br></blockquote><div><br></div><div>Yes. As long as the QObject is moved to a QThread (*any* QThread), the slot is executed in that thread.</div><div>The started() signal behaves just like any signal, *but* while it is sent from the QThread emitting the signal, the *thread* of the emission is that on which the QThread is wrapped around.</div><div>So, when the thread is started, the started() signal is emitted from that QThread, but in the thread that QThread is wrapped around; then, if the thread of the receiver is on another thread (typically, by using moveToThread), the function will be executed in that target thread.</div><div><br></div><div>This can be very confusing, I know. The fact is that moveToThread actually means "move to the thread that is managed by that QThread". That's why you can actually use moveToThread on the QThread (self.moveToThread(self)), which is probably one of the reasons for the confusion that caused the infamous Qt blog post.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">> Finally, you could still subclass a QThread and implement a "worker <br>
> function" in that thread (thus allowing the default implementation to <br>
> execute and use the thread's event loop): just give it a different name <br>
> and connect it to the started signal.<br></blockquote><div><br></div><div>An important clarification about this: in order to *actually* run a worker function in the thread of a QThread subclass, that QThread requires moving it to itself (as explained above). This is an important aspect that wasn't properly explained in my previous message.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On this subject I would suggest looking at QRunnable and QThreadPool as <br>
they provide an higher level interface for background workers that don't <br>
need much interaction<br></blockquote><div><br></div><div>QRunnable is a very interesting interface, but has the obvious drawback of not being a QObject subclass, so it doesn't support signals. Its concurrent reusability, though, is a major benefit, and adding a *single* QObject "proxy" within a unique QRunnable instance can be really useful, if properly implemented.</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Let me say thank you for writing down this exhaustive analysis (which <br>
admittedly is far better than my 2 lines answer).<br></blockquote><div><br></div><div>You're very welcome :-) I learnt all this "the hard way", so it seems only obvious to me to share my experience with others. It took me a lot of time to understand all these aspects on my own, and writing such answers also helps me to even dig deeper in that knowledge, so it actually brings benefits to myself too...</div></div><br clear="all"><div>Maurizio</div>-- <br><div dir="ltr">È difficile avere una convinzione precisa quando si parla delle ragioni del cuore. - "Sostiene Pereira", Antonio Tabucchi<br><a href="http://www.jidesk.net" target="_blank">http://www.jidesk.net</a></div></div></div></div></div>