Slot In Qthread
2021年10月9日Register here: http://gg.gg/w65rr
*Signal And Slot In Qthread
*Invoke Slot In Qthread
This post is about the use of QThread. It is an answer to a three years old blog post by Brad, my colleague at the time:
You’re doing it wrong
In his blog post,Brad explains that he saw many users misusing QThread by sub-classing it, adding someslots to that subclass and doing something like this in the constructor:
*The worker thread is implemented as a PyQt thread rather than a Python thread since we want to take advantage of the signals and slots mechanism to communicate with the main application. Class Worker(QThread): def init(self, parent = None): QThread.init(self, parent) self.exiting = False self.size = QSize(0, 0) self.stars = 0.
*Example for QThread without inheriting from QThread directly, but changing thread affinity of QObject via obj-moveToThread(thread). New QT Connection syntax. This is a example how to add QObject to an QThread via MoveToThread. The goal is to achieve a constantly updating list, which will then be processed.
They move a thread to itself. As Brad mentions, it is wrong: the QThread is supposed tobe the interface to manage the thread. So it is supposed to be used from the creating thread.
Slots in the QThread object are then not run in that thread and having slots in a subclass of QThreadis a bad practice.
With a direct connection, the slot will be called by the current thread that is emitting the signal. Usually, this is very bad, if the two objects live in different threads. There are cases where you can do this – one example could be a slot that locks a mutex, adds something to a queue, unlocks and returns. Wanneer het wordt uitgevoerd met QThreadPool wordt de methode run van mijn uitvoerbare naam opgeroepen vanuit een gepoolde thread (ik controleer dit met QThread:: currentThread ), maar mijn slots lopen niet in de gepoolde thread, dus ik denk dat het object niet is verplaatst naar een thread in het zwembad.
But then Brad continues and discourages any sub-classing of QThread at all.He claims it is against proper object-oriented design.This is where I disagree. Putting code in run() is a valid object-oriented way to extend a QThread:A QThread represents a thread that just starts an event loop, a subclass represents a threadthat is extended to do what’s in run().
After Brad’s post, some members of the community went on a crusade against sub-classing QThread.The problem is that there are many perfectly valid reasons to subclass QThread.
With Qt 5.0 and Qt 4.8.4, the documentation of QThread was changed so the sample code does not involvesub-classing.Look at the first code sampleof the Qt 4.8 QThread documentation (Update: link to archive.org since the newer documentation is fixed).It has many lines of boiler plate just to run some code in a thread. And the there is evena leak: the QThread is never going to quit and be destroyed.
A QObject::connect statement may fail diamond jo casino iowa map to qt signal slot qthread connect a signal to a slot for various reasons. The slot is executed in closest slot machines to san jose ca the receiver’s thread.It is necessary to call qt signal slot qthread this function to start event handling. Void update; QThread inherits QObject.
I was asked on IRC a question from an user who followed that example in orderto run some simple code in a thread. He had a hard time to figure out how to properlydestroy the thread. That is what motivated me to write this blog entry.
If you allow to subclass QThread, this is what you got:
This code does no longer leak and is much simpler and has lessoverhead as it does not create useless object.
The Qt threading examplethreadedfortuneserveris an example that uses this pattern to run blocking operations and is much simpler thanthe equivalent using a worker object.
I have submitted a patch to the documentationto not discourage sub-classing QThread anymore.Rules of thumbs
When to subclass and when not to?
*If you do not really need an event loop in the thread, you should subclass.
*If you need an event loop and handle signals and slots within the thread, you may not need to subclass.What about using QtConcurrent instead?
QThread is a quite low level and you should better use a higher levelAPI such as QtConcurrent.
Now, QtConcurrent has its own set of problems: It is tied to a single thread pool so it is nota good solution if you want to run blocking operations. It has also some problems in itsimplementation that gives some performance overhead. All of this is fixable.Perhaps even Qt 5.1 will see some improvements.
A good alternative is also the C++11 standard library withstd::threadand std::async which arenow the standard way to run code in a thread. And the good news is that it still works fine with Qt:All other Qt threading primitives can be used with native threads.(Qt will create automatically create a QThread if required).
There are basically two different ways of using QThread directly: Worker threads or subclassing. Those two are confusing to a lot of developers, and I will try to explain when you should use those. I will also explain how signals and slots work with threads and how they can help you or lead to problems.
There are other ways to use QThread than those two. There are hybrid cases that lie somewhere between the two general classes, and you can use QThreadPool or the QtConcurrent. Those cases will not be described here, but I might come back to those in later blog posts.
When you look at the discussion on whether or not to subclass QThread, you will find a lot of people who claim this is bad. For example the famous “You’re doing it wrong” blog post from 2010 (yes, this is an old discussion). I have mixed feelings about this blog post and the arguments it presents. On one hand, I actually encourage developers to follow the recommendations in this article, because I agree that this is the path that leads to fewer errors in your code. OTOH, there are certainly valid use cases for subclassing.
The fundamental problem here is that most developers do not really understand the thread model of Qt. And in some cases they do not even understand threading at all. There are a lot of developers in this industry who should not touch multithreaded code at all, but still have tasks in their daily job that force them to do this. I won’t try to educate general thread development here, but I will encourage everyone who needs to learn this to read a good book on multithreaded development. I’m only going to talk about the QThread class here and assume you understand threading.
So let’s get started on the issue at hand.
There are two Qt technologies that you need to understand before you can understand why QThread works the way it does.QObject thread affinity
The first of those two technologies is thread affinity. Each QObject has a thread that it belongs to. Unless you set this manually, QObject chooses the current thread when the constructor is run.
Thread affinity has a bunch of subtle consequences for our objects, once you start going multithreaded. Of course, if you don’t have any threads, the objects all live in the main thread, and then you don’t have to worry about it. But with threading, you do have to worry about it.
The first thing you have to know is what this means for signals and slots.
When you do a connect from a signal to a slot, you have a choice of connection type. Those can be automatic, direct or queued. Yes, there are a couple of others, but those are not interesting from a threading point of view.
With a direct connection, the slot will be called by the current thread that is emitting the signal. Usually, this is very bad, if the two objects live in different threads. There are cases where you can do this – one example could be a slot that locks a mutex, adds something to a queue, unlocks and returns. But you have a problem if the object can be deleted by another thread while your slot is being executed, of course. My recommendation is not to use this unless you absolutely have to, you really know what you are doing, and make sure you document both sides very precisely.
For queued connections to work, the thread where the receiving object lives (i.e. has the thread affinity), must have an active event loop. This is not necessary for the sender. What happens is that the sending signal will create an event with the arguments of the signal and send this event to the receiver thread eventloop. In the eventloop, the event is transformed to a normal slot call. This happens no matter if the two objects live in the same thread or if they are in different threads. (And this is one of the simplest ways to send information from one thread to another.)
Automatic connection does a check in the signal whether the thread affinity of the receiver is the same as the current thread. If these are the same, it does a direct signal to slot call. If they are different, this is handled as a queued connection. This check is done every time the signal is emitted, which means the thread of the signal is irrelevant and the connect just works. Note that the signalling object does not have to live in a thread with an event loop.QThread thread affinity
The second thing you need to understand, is the thread affinity of the QThread object. This is the part that confuses a lot of developers, although the rules are actually quite simple.
The thread affinity of a QThread object is the creating thread. It does not live in the thread that it models and implements. This may sound counterintuitive, until you actually think about this.
First, when you create the QThread object, the new thread doesn’t exist. This means the constructor will necessarily have to run in the thread that creates it. Also, when the thread is finished and you want to delete it, this will be done in the creating thread as well, so the destructor runs in the creating thread.
However, in the run method of QThread, you are now in the new thread.
This means when you create objects in a QThread subclass method, they will have different thread affinity based on the instantiation time. L’auberge casino & hotel baton rouge jobs. If you create an object in the constructor (or in the destructor, but that’s rare) this object will have the calling thread affinity. If you create an object in the run method, this will have the new thread affinity. If you have a method on the QThread subclass, an object created in here will (as usual) have the current thread affinity – so if you call it from the constructor it will have the creating thread affinity, and if you call it from run it will have the new thread affinity.
For signals, the thread affinity doesn’t matter. But for slots it matters a lot.Signal And Slot In QthreadSubclassing QThread
Now you can perhaps appreciate why subclassing QThread can be a problem. If you have anything using slots in the subclass objects, the thread affinity will mean that it will use the original thread. This is also the case for lambda slots or what other tricks you could come up with.
So, to “fix” this, developers try various workarounds. First, they use moveToThread(this) on the thread object. Unfortunately, this is probably the worst thing you can do, because that is a violation of the basic assumption of QThread itself. Others will connect using the DirectConnection flag, which actually works, but is a very brittle solution that probably will break while people are working on the code in the years to come.Invoke Slot In Qthread
The next problem you have to consider is when you instantiate other objects from the thread object itself. If you want an object to live in the new thread, you must instantiate it inside the run method and not set the thread object as the parent, because Qt does not like the parent-child relationship to go across from one thread to another.Recommendations
So, now we’re finally ready for a list of what you should do in different cases.
If you have a task you need to run in a QThread, this is the place where you do as the QThread documentation says, and create a worker thread. Just instantiate a QThread object, instantiate the objects to live in this thread, call moveToThread(thread) on those objects and start the thread. This is what you should do for most cases.
If you have something that’s just a pure calculation or something that connects to hardware, then you will often use a QThread subclass. Yes, you can implement this using worker threads as well, but that’s usually a silly way to do it. (For the pure calculation case, I would actually use QtConcurrent or the QThreadPool, but that’s a topic for a later blog post.)
When you look at this recommendation, there are two things that are the defining questions:
*Do you need slots?
*Do you need QObject instances in the new thread?
If the answer to one of those questions is yes, then you should follow the standard recommendation and use a worker thread. If the answer is no, you have a choice between subclassing and worker threads.
If you answer yes to either of those questions and still choose subclassing, you are probably going to have issues that are really hard to find. Remember, there’s actually a reason people suggest that you don’t subclass QThread. If you do it, you expose yourself to a couple of sets of problems that you don’t have when you use a worker thread.
Register here: http://gg.gg/w65rr
https://diarynote.indered.space
*Signal And Slot In Qthread
*Invoke Slot In Qthread
This post is about the use of QThread. It is an answer to a three years old blog post by Brad, my colleague at the time:
You’re doing it wrong
In his blog post,Brad explains that he saw many users misusing QThread by sub-classing it, adding someslots to that subclass and doing something like this in the constructor:
*The worker thread is implemented as a PyQt thread rather than a Python thread since we want to take advantage of the signals and slots mechanism to communicate with the main application. Class Worker(QThread): def init(self, parent = None): QThread.init(self, parent) self.exiting = False self.size = QSize(0, 0) self.stars = 0.
*Example for QThread without inheriting from QThread directly, but changing thread affinity of QObject via obj-moveToThread(thread). New QT Connection syntax. This is a example how to add QObject to an QThread via MoveToThread. The goal is to achieve a constantly updating list, which will then be processed.
They move a thread to itself. As Brad mentions, it is wrong: the QThread is supposed tobe the interface to manage the thread. So it is supposed to be used from the creating thread.
Slots in the QThread object are then not run in that thread and having slots in a subclass of QThreadis a bad practice.
With a direct connection, the slot will be called by the current thread that is emitting the signal. Usually, this is very bad, if the two objects live in different threads. There are cases where you can do this – one example could be a slot that locks a mutex, adds something to a queue, unlocks and returns. Wanneer het wordt uitgevoerd met QThreadPool wordt de methode run van mijn uitvoerbare naam opgeroepen vanuit een gepoolde thread (ik controleer dit met QThread:: currentThread ), maar mijn slots lopen niet in de gepoolde thread, dus ik denk dat het object niet is verplaatst naar een thread in het zwembad.
But then Brad continues and discourages any sub-classing of QThread at all.He claims it is against proper object-oriented design.This is where I disagree. Putting code in run() is a valid object-oriented way to extend a QThread:A QThread represents a thread that just starts an event loop, a subclass represents a threadthat is extended to do what’s in run().
After Brad’s post, some members of the community went on a crusade against sub-classing QThread.The problem is that there are many perfectly valid reasons to subclass QThread.
With Qt 5.0 and Qt 4.8.4, the documentation of QThread was changed so the sample code does not involvesub-classing.Look at the first code sampleof the Qt 4.8 QThread documentation (Update: link to archive.org since the newer documentation is fixed).It has many lines of boiler plate just to run some code in a thread. And the there is evena leak: the QThread is never going to quit and be destroyed.
A QObject::connect statement may fail diamond jo casino iowa map to qt signal slot qthread connect a signal to a slot for various reasons. The slot is executed in closest slot machines to san jose ca the receiver’s thread.It is necessary to call qt signal slot qthread this function to start event handling. Void update; QThread inherits QObject.
I was asked on IRC a question from an user who followed that example in orderto run some simple code in a thread. He had a hard time to figure out how to properlydestroy the thread. That is what motivated me to write this blog entry.
If you allow to subclass QThread, this is what you got:
This code does no longer leak and is much simpler and has lessoverhead as it does not create useless object.
The Qt threading examplethreadedfortuneserveris an example that uses this pattern to run blocking operations and is much simpler thanthe equivalent using a worker object.
I have submitted a patch to the documentationto not discourage sub-classing QThread anymore.Rules of thumbs
When to subclass and when not to?
*If you do not really need an event loop in the thread, you should subclass.
*If you need an event loop and handle signals and slots within the thread, you may not need to subclass.What about using QtConcurrent instead?
QThread is a quite low level and you should better use a higher levelAPI such as QtConcurrent.
Now, QtConcurrent has its own set of problems: It is tied to a single thread pool so it is nota good solution if you want to run blocking operations. It has also some problems in itsimplementation that gives some performance overhead. All of this is fixable.Perhaps even Qt 5.1 will see some improvements.
A good alternative is also the C++11 standard library withstd::threadand std::async which arenow the standard way to run code in a thread. And the good news is that it still works fine with Qt:All other Qt threading primitives can be used with native threads.(Qt will create automatically create a QThread if required).
There are basically two different ways of using QThread directly: Worker threads or subclassing. Those two are confusing to a lot of developers, and I will try to explain when you should use those. I will also explain how signals and slots work with threads and how they can help you or lead to problems.
There are other ways to use QThread than those two. There are hybrid cases that lie somewhere between the two general classes, and you can use QThreadPool or the QtConcurrent. Those cases will not be described here, but I might come back to those in later blog posts.
When you look at the discussion on whether or not to subclass QThread, you will find a lot of people who claim this is bad. For example the famous “You’re doing it wrong” blog post from 2010 (yes, this is an old discussion). I have mixed feelings about this blog post and the arguments it presents. On one hand, I actually encourage developers to follow the recommendations in this article, because I agree that this is the path that leads to fewer errors in your code. OTOH, there are certainly valid use cases for subclassing.
The fundamental problem here is that most developers do not really understand the thread model of Qt. And in some cases they do not even understand threading at all. There are a lot of developers in this industry who should not touch multithreaded code at all, but still have tasks in their daily job that force them to do this. I won’t try to educate general thread development here, but I will encourage everyone who needs to learn this to read a good book on multithreaded development. I’m only going to talk about the QThread class here and assume you understand threading.
So let’s get started on the issue at hand.
There are two Qt technologies that you need to understand before you can understand why QThread works the way it does.QObject thread affinity
The first of those two technologies is thread affinity. Each QObject has a thread that it belongs to. Unless you set this manually, QObject chooses the current thread when the constructor is run.
Thread affinity has a bunch of subtle consequences for our objects, once you start going multithreaded. Of course, if you don’t have any threads, the objects all live in the main thread, and then you don’t have to worry about it. But with threading, you do have to worry about it.
The first thing you have to know is what this means for signals and slots.
When you do a connect from a signal to a slot, you have a choice of connection type. Those can be automatic, direct or queued. Yes, there are a couple of others, but those are not interesting from a threading point of view.
With a direct connection, the slot will be called by the current thread that is emitting the signal. Usually, this is very bad, if the two objects live in different threads. There are cases where you can do this – one example could be a slot that locks a mutex, adds something to a queue, unlocks and returns. But you have a problem if the object can be deleted by another thread while your slot is being executed, of course. My recommendation is not to use this unless you absolutely have to, you really know what you are doing, and make sure you document both sides very precisely.
For queued connections to work, the thread where the receiving object lives (i.e. has the thread affinity), must have an active event loop. This is not necessary for the sender. What happens is that the sending signal will create an event with the arguments of the signal and send this event to the receiver thread eventloop. In the eventloop, the event is transformed to a normal slot call. This happens no matter if the two objects live in the same thread or if they are in different threads. (And this is one of the simplest ways to send information from one thread to another.)
Automatic connection does a check in the signal whether the thread affinity of the receiver is the same as the current thread. If these are the same, it does a direct signal to slot call. If they are different, this is handled as a queued connection. This check is done every time the signal is emitted, which means the thread of the signal is irrelevant and the connect just works. Note that the signalling object does not have to live in a thread with an event loop.QThread thread affinity
The second thing you need to understand, is the thread affinity of the QThread object. This is the part that confuses a lot of developers, although the rules are actually quite simple.
The thread affinity of a QThread object is the creating thread. It does not live in the thread that it models and implements. This may sound counterintuitive, until you actually think about this.
First, when you create the QThread object, the new thread doesn’t exist. This means the constructor will necessarily have to run in the thread that creates it. Also, when the thread is finished and you want to delete it, this will be done in the creating thread as well, so the destructor runs in the creating thread.
However, in the run method of QThread, you are now in the new thread.
This means when you create objects in a QThread subclass method, they will have different thread affinity based on the instantiation time. L’auberge casino & hotel baton rouge jobs. If you create an object in the constructor (or in the destructor, but that’s rare) this object will have the calling thread affinity. If you create an object in the run method, this will have the new thread affinity. If you have a method on the QThread subclass, an object created in here will (as usual) have the current thread affinity – so if you call it from the constructor it will have the creating thread affinity, and if you call it from run it will have the new thread affinity.
For signals, the thread affinity doesn’t matter. But for slots it matters a lot.Signal And Slot In QthreadSubclassing QThread
Now you can perhaps appreciate why subclassing QThread can be a problem. If you have anything using slots in the subclass objects, the thread affinity will mean that it will use the original thread. This is also the case for lambda slots or what other tricks you could come up with.
So, to “fix” this, developers try various workarounds. First, they use moveToThread(this) on the thread object. Unfortunately, this is probably the worst thing you can do, because that is a violation of the basic assumption of QThread itself. Others will connect using the DirectConnection flag, which actually works, but is a very brittle solution that probably will break while people are working on the code in the years to come.Invoke Slot In Qthread
The next problem you have to consider is when you instantiate other objects from the thread object itself. If you want an object to live in the new thread, you must instantiate it inside the run method and not set the thread object as the parent, because Qt does not like the parent-child relationship to go across from one thread to another.Recommendations
So, now we’re finally ready for a list of what you should do in different cases.
If you have a task you need to run in a QThread, this is the place where you do as the QThread documentation says, and create a worker thread. Just instantiate a QThread object, instantiate the objects to live in this thread, call moveToThread(thread) on those objects and start the thread. This is what you should do for most cases.
If you have something that’s just a pure calculation or something that connects to hardware, then you will often use a QThread subclass. Yes, you can implement this using worker threads as well, but that’s usually a silly way to do it. (For the pure calculation case, I would actually use QtConcurrent or the QThreadPool, but that’s a topic for a later blog post.)
When you look at this recommendation, there are two things that are the defining questions:
*Do you need slots?
*Do you need QObject instances in the new thread?
If the answer to one of those questions is yes, then you should follow the standard recommendation and use a worker thread. If the answer is no, you have a choice between subclassing and worker threads.
If you answer yes to either of those questions and still choose subclassing, you are probably going to have issues that are really hard to find. Remember, there’s actually a reason people suggest that you don’t subclass QThread. If you do it, you expose yourself to a couple of sets of problems that you don’t have when you use a worker thread.
Register here: http://gg.gg/w65rr
https://diarynote.indered.space
コメント