Qthread seems to be a very difficult thing, especially the signals and slots, there are a lot of people (although users themselves often do not know) in the use of inappropriate (or even wrong) way in using Qthread, casually with Google search, can search out a large number of results. No wonder the QT developer Bradley T. Hughes screaming to you Are-doing-it-wrong
Like many users, the first time I saw this, I felt Bradley T Hughes was a little strange and frivolous. Despite the discomfort, it was a blog qthread how to use
The past 3 months, although still not how to use thread, but today CSDN forum Someone asked this question, think about it or do my best to tidy it up. Improve yourself, convenience to others, why not?
Qthread things are still more, and I have limited knowledge of the underlying objects, just a little bit to expand (perhaps the most concern of everyone):Qthread in the slots in that thread execution?
Qthread::run
What does the run function do? The manual said clearly:
- Run acts on the thread as the main function for the application. It is the thread's entry, and the start and end of the run means the start and end of the thread.
The original text is as follows (this passage we call the theorem One bar):
- The run () implementation is for a thread, the main () entry point was for the application. All code executed in a call stack that starts in the run () function is executed by the new thread, and the thread finishes When the function returns.
This short text at a glance is finished, but, what does this mean? What can be explained? See section Simple code:
Class Thread:public Qthread
{
Q_object
Public
Thread (qobject* parent=0): Qthread (parent) {}
Public Slots:
void slot () {...}
Signals:
void Sig ();
Protected
void Run () {...}
};
int main (int argc, char** argv)
{
...
Thread thread;
...
}
In contrast to the previous theorem, the code in the run function is definitely going to run in the secondary thread, what about the other? For example, does the slot run in the secondary or main thread?
You want to say the main thread, but you're unwilling, right?
Qobject::connect
When it comes to signal slots, we can't hide from the Connect function, but this function is very familiar to everyone. I am embarrassed to use a lot of nonsense to describe it, but do not say no, then compromise, just look at its last parameter (for the sake of simplicity, only see its most commonly used 3 values)
In the following list, we are temporarily called theorem two :
- Automatic connection (auto Connection)
- This is the default setting
- If the signal is emitted within the thread that the receiver is attached to, it is equivalent to a direct connection
- If the thread that emits the signal is different from the thread to which the recipient is attached, it is equivalent to a queue connection
- That is to say, there are only two of the following
- Direct connection (directly Connection)
- When the signal is emitted, the slot function is called directly.
- The slot function executes within the thread that emits the signal, regardless of which thread the slot function belongs to.
- Queue connection (Queued Connection)
- The slot function is called when control returns to the event loop of the thread to which the recipient is attached.
- The slot function executes on the thread attached to the receiver.
Like the previous face, these words can be read by everyone. But what does it mean?
Let's continue with the previous example to see if the slot function is executed in the main thread or in the threads.
Theorem two emphasizes two concepts: the thread that sends the signal and the thread that the receiver is attached to . The slot function is the thread of the object we created in main, where thread is attached to the main thread
- The queue connection tells us that the slot function executes on the thread that the recipient is attached to. That is, the slot is executed on the main thread
- The direct connection tells us that the slot function executes on the thread that sends the signal. What is the signal sent on that thread?? Indefinite!
- Automatic connection tells us: The two are different, the same as the queue connection. That is, the slot executes on the main thread
Is it too round? (To understand these words thoroughly, you may need to look at the QT meta-object system and the QT Event System)
What do we do?
If you do not understand the last two sections, remember the following words (oneself summed up, in terms of estimates will be less accurate).
- Qthread is used to manage threads, the threads it attaches to and the threads it manages are not the same thing.
- The thread on which Qthread is attached is the thread that executes Qthread t (0) or Qthread * t=new qthread (0). That's the main thread of our place.
- The thread that Qthread manages is the thread that run starts. That is, the secondary thread
- Because the Qthread object is attached to the main thread, his slot function executes in the main thread, not the secondary thread. Unless:
- Qthread object attached to sub-line approached (via Movetothread)
- Slots and signals are directly connected, and the signal is emitted in the secondary thread
- But the last two solutions are not good, because qthread is not so used (Bradley T. Hughes)
OK, no more text to add, look at the code, I guess we'll be easy.
Main thread (signal) Qthread (slot)
This is a commonly used method in Qt Manual and examples. But since manual does not say that the slot function is executed in the main thread, many people think it should be executed on the secondary threads.
- Define a Dummy class to signal
- Define a Thread class to receive the signal
- The run function is overloaded to print ThreadID
/*!
* \file main.cpp
*
* Copyright (C), dbzhang800
* All rights reserved.
*
*/
#include <QtCore/QCoreApplication>
#include <QtCore/QObject>
#include <QtCore/QThread>
#include <QtCore/QDebug>
Class Dummy:public Qobject
{
Q_object
Public
Dummy () {}
Public Slots:
void Emitsig ()
{
Emit sig ();
}
Signals:
void Sig ();
};
Class Thread:public Qthread
{
Q_object
Public
Thread (qobject* parent=0): Qthread (parent)
{
Movetothread (this);
}
Public Slots:
void Slot_main ()
{
Qdebug () << "from thread Slot_main:" <<currentthreadid ();
}
Protected
void Run ()
{
Qdebug () << "thread Thread:" <<currentthreadid ();
exec ();
}
};
#include "Main.moc"
int main (int argc, char *argv[])
{
Qcoreapplication A (argc, argv);
Qdebug () << "main thread:" <<qthread::currentthreadid ();
Thread thread;
Dummy Dummy;
Qobject::connect (&dummy, SIGNAL (Sig ()), &thread, SLOT (Slot_main ()));
Thread.Start ();
Dummy.emitsig ();
return A.exec ();
}
then see the result (the exact value changes every time, but the conclusion is unchanged)
Main THREAD:0X1A40 from thread slot_main:0x1a40 thread Thread:0x1a48
See, the Slot function thread is the same as the main line!
If you have seen the example of QT, you will find that the Qthread in the slot and the run function in conjunction with the object, will be locked with Qmutex. Why?
Because slots and run are in different threads, synchronization between threads is required!
What if you want the slot function slot to run on a sub-thread (for example, if it does a time-consuming operation that will cause the main thread to die)?
- Note: The dummy signal is emitted on the main thread, and the receiver thread is also in the main thread.
- Referring to our previous conclusions, it is easy to think of:
- Would you like to change thread-dependent threads to a secondary thread?
- This is also done with the commented out Movetothread (this) in the code, minus the comments, and you'll notice that the slots run in the secondary thread
Main THREAD:0X13C0
Thread Thread:0x1de0
From Thread slot_main:0x1de0
This can work, but this is the use of Bradley T. Hughes's strong critique . The recommended method is given later.
Signal in run and Qthread in slot
- Define a Dummy class that emits its signal in run
- You can also emit a signal from the Thread class in run, not dummy (the effect is exactly the same)
- Qthread defining a slot function, overloading the run function
/*!
* \file main.cpp
*
* Copyright (C), dbzhang800
* All rights reserved.
*
*/
#include <QtCore/QCoreApplication>
#include <QtCore/QObject>
#include <QtCore/QThread>
#include <QtCore/QDebug>
Class Dummy:public Qobject
{
Q_object
Public
Dummy (qobject* parent=0): Qobject (parent) {}
Public Slots:
void Emitsig ()
{
Emit sig ();
}
Signals:
void Sig ();
};
Class Thread:public Qthread
{
Q_object
Public
Thread (qobject* parent=0): Qthread (parent)
{
Movetothread (this);
}
Public Slots:
void Slot_thread ()
{
Qdebug () << "from thread Slot_thread:" <<currentthreadid ();
}
Signals:
void Sig ();
Protected
void Run ()
{
Qdebug () << "thread Thread:" <<currentthreadid ();
Dummy Dummy;
Connect (&dummy, SIGNAL (Sig ()), this, SLOT (Slot_thread ()));
Dummy.emitsig ();
exec ();
}
};
#include "Main.moc"
int main (int argc, char *argv[])
{
Qcoreapplication A (argc, argv);
Qdebug () << "main thread:" <<qthread::currentthreadid ();
Thread thread;
Thread.Start ();
return A.exec ();
}
Want to see the results?
Main THREAD:0X15C0
Thread thread:0x1750
From Thread slot_thread:0x15c0
- In fact, no suspense, it must be the main thread
- The thread object itself is in the main thread. So its slots are going to be executed in the main thread.
How to solve it?
- (method i) mentioned movetothread, here can be used, and can solve the problem. When the same, is the object of being criticized.
- (method Two) Note oh, here our signal when the second thread, compared to connect connection mode, will find:
- With a direct connection, the slot function executes on the secondary thread (the signal-emitting thread)
- This method is not very good because you need to handle the synchronization of the slot and the thread on which it is located. Need to qmutex a class of things
Recommended method
Awaited began to come out.
In fact, this method is too simple, too useful. Define a generic Qobject derived class, and then move its objects to qthread. There is no need to consider multithreading when using signals and slots. Also do not use Qmutex to synchronize, QT event loop will automatically handle this.
/*!
* \file main.cpp
*
* Copyright (C), dbzhang800
* All rights reserved.
*
*/
#include <QtCore/QCoreApplication>
#include <QtCore/QObject>
#include <QtCore/QThread>
#include <QtCore/QDebug>
Class Dummy:public Qobject
{
Q_object
Public
Dummy (qobject* parent=0): Qobject (parent) {}
Public Slots:
void Emitsig ()
{
Emit sig ();
}
Signals:
void Sig ();
};
Class Object:public Qobject
{
Q_object
Public
Object () {}
Public Slots:
void slot ()
{
Qdebug () << "from thread slot:" <<qthread::currentthreadid ();
}
};
#include "Main.moc"
int main (int argc, char *argv[])
{
Qcoreapplication A (argc, argv);
Qdebug () << "main thread:" <<qthread::currentthreadid ();
Qthread thread;
Object obj;
Dummy Dummy;
Obj.movetothread (&thread);
Qobject::connect (&dummy, SIGNAL (Sig ()), &obj, slot (slot ()));
Thread.Start ();
Dummy.emitsig ();
return A.exec ();
}
Result: Yes, the slot does not run in the main thread (so simple isn't it worth cheering for?). )
Main THREAD:0X1A5C
From Thread slot:0x186c Other
- This article only considers the use of event loops, and it is possible that there is no event loop in run. At this point the signal and groove will be a bit different from this article. For example, when you use connect in run, the queue connection is restricted. In fact, as long as the understanding of the above, there is no event cycle of the situation is easy to understand.
See
Http://doc.qt.nokia.com/4.7/threads-starting.html
Http://doc.qt.nokia.com/4.7/threads-qobject.html
Http://doc.qt.nokia.com/4.7/qthread.html
[Turn]-Discussion on application of Qthread