Is it possible to implement a poll with QThread without subclassing it?

I have a class that is an abstraction of some device.

class Device { public: ... void Start(); void Stop(); void MsgLoop(); signals: void sMsgArrived(); } 

Start () and Stop () are called from the GUI thread. Start () starts a new thread that starts MsgLoop (). It looks like this:

 void MsgLoop() { forever { if(SUCCESS == ReadMsg()) //synchronous, non-blocking { ProcessMsg(); //quite fast emit sMsgArrived(); //this signal is connected with a slot in GUI thread } } } 

When Stop () is called, the program should return from MsgLoop () and stop the thread. How can I implement this with QThread without subclassing it?

+3
source share
3 answers

Generally, you must decide who will be responsible for managing the flow. Is this device or main window? Or maybe some kind of device manager. In your case, the device should probably control its own stream, so if you don't want to subclass it, use the composition:

 class Device : QObject { Q_OBJECT public: Device(QObject * parent = NULL); void Start(); void Stop(); private slots: void MsgLoop(); signals: void sMsgArrived(); private: QThread thread; bool stopThread; }; Device::Device(QObject * parent) : QObject(parent) { moveToThread(&thread); connect(&thread, SIGNAL(started()), this, SLOT(MsgLoop())); } void Device::Start() { stopThread = false; thread.start(); } void Device::Stop() { stopThread = true; thread.wait(); // if you want synchronous stop } void Device::MsgLoop() { // your loop while(!stopThread) if(SUCCESS == ReadMsg()) { ProcessMsg(); emit sMsgArrived(); } QThread::currentThread->quit(); } 

NOTE: stopping the thread will only work if ReadMsg is not really blocking. If you later decide to switch to read lock (and this will probably be appropriate for most cases), you will have to figure out how to stop the stream.

+4
source

If you look at the link you will see that you can run the method in a separate thread without subclassing QThread.

However, what you request is to start the message loop forever .

If you follow the example above, you can run the loop without subclassing, but the QThread object will never go into its own message loop , because it will never return from your slot. So here is an example, but I think it will be a bad design

 class Device : public QObject { Q_OBJECT public: Device(QObject* parent = 0); ~Device(); public Q_SLOTS: void MsgLoop(); }; QThread* thread = new QThread; Device* device = new Device; void Widget::onBtnStartClicked() { device->moveToThread(thread); //This will call start method of Device connect(thread, SIGNAL(started()), device, SLOT(MsgLoop())); //This will start the event loop of thread thread->start(); } void Widget::onBtnStopClicked() { //Tells the thread to exit thread->exit(0); } 

I am afraid that you need to subclass QThread if you want to start the forever loop.

+2
source

IMHO you should not. The survey requires availability in a continuous cycle. You must do this in the QThread launch function so that it is not possible to reimplement the function without sub-classification in the first place. Even if you try a workaround with a one-shot timer, I do not recommend it. You better (this is how I like to do this) by subclassing QThread by calling moveToThread () rather than calling exec () and putting the forever loop in run. An example of this example can be found in the qt example of the Fortune remote client. If you do not call moveToThread () in QThread, then the QThread object is still in the main thread of the graphical user interface, and both of them share the same event loop (which is bad when using the polling functions). Calling moveToThread (QThread) without calling exec () means that QThread will not have an event loop (which is good in your case). A call to exec () would trigger its own event loop, but was not used for polling schemes, and you would leave the trigger function.

0
source

All Articles