Qt sends signals and metadata across threads, and qt sends metadata across threads.

Source: Internet
Author: User

Qt sends signals and metadata across threads, and qt sends metadata across threads.

Reprinted please indicate the source: http://blog.csdn.net/luotuo44/article/details/39395025



Qt signals/slots can be used between threads. Because the event loop is completed in the main thread, when the non-main thread sends a signal, the corresponding slot function will be executed by the main thread.



Readers familiar with multithreading should all feel that there is a subtle problem. If the function parameters of signals/slots are of a defined type. For example, you have defined a Student class, and the signal function is sendStudent (const Student & stu); the corresponding slot function is: getStudent (const Student & stu ); if the Student parameter is a temporary variable when the non-main thread uses emit to send signals (that is, it may be immediately defactored ), the temporary variable may be parsed when the main thread executes this slot function. This is equivalent to using a wild pointer.

 

The author of Qt must have thought of this.

In the connect function, we generally only use four parameters. In fact, it has five parameters, but uses the default parameters. The fifth parameter is an enumeration type Qt: ConnectionType, which has the following five types:

  • Qt: AutoConnection: If the thread sending the signal is in the same thread as the thread executing the slot function, it is equivalent to Qt: DirectConnection. If not in the same thread, it is equivalent to Qt: QueuedConnection. This is the default parameter of the connect function.
  • Qt: DirectConnection: the transmitting signal and execution slot are completed by the same thread. The slot function is executed immediately. The code after "emit signal" is executed. That is, the "emit signal" is blocked.
  • Qt: QueuedConnection: the thread that emits signals and the thread that executes the slot function are not in the same thread. At this time, the thread that emits the signal is not blocked and returns immediately. When the thread executing the slot function is scheduled by the CPU, the slot function is executed.
  • Qt: BlockingQueuedConnection: is basically the same as Qt: QueuedConnection, but the thread that emits the signal is blocked and the slot function is executed. Therefore, if this connect attribute is set, make sure that the transmit signal thread is not the thread that executes the slot function. Otherwise, a deadlock will occur.
  • Qt: UniqueConnection: unique association. That is, the same signal and the same slot can only call connect once. It cannot be called multiple times. Note: At this time, a signal can still be associated with multiple slots.

In the above enumeration, it indicates whether the thread is in the same thread. Its judgment is also simple. The thread that executes the slot function is the thread that executes the event loop, that is, the thread that executes the QCoreApplication a (argc, argv); a.exe c () function. Generally, the main thread executes the event loop. The launch thread is the thread that calls emit.

 

From the above association type, we can see that the author of Qt is the thread that considers the signal to be sent, not the thread that executes the slot function. So how does Qt solve the subtle problem just now? The answer is metadata. Call qregisterype <Student> ("Student") before calling connect; register this Student type as metadata. In this way, the problem can be avoided.

 


 

Since I didn't read the source code of Qt, I don't know how to implement it in Qt. I regard the implementation of Qt as a black box and use a document and test to make some guesses. The following is my conjecture, which is not necessarily correct.


If this problem is solved by ourselves, we can think of the method of copying a Student class internally. In this way, no matter whether the Temporary Student Of the launch thread is parsed or not.

By reading the qregisterpolicype entry of the Qt assistant, you can see that it is conditional to register a type as metadata. The default constructor, copy constructor, and destructor of the public attribute must be provided for this type. This should be to copy a Student. Haha. The following is an example.

Header file:

# Ifndef TK_HPP # define TK_HPP # include <QString> # include <QThread> # include <QDebug> class Student {public: Student () {} Student (const QString & name, const QString & id): m_name (name), m_id (id) {} Student (const Student & stu) {// assign values in this way intentionally. It means that Qt cannot be copied and constructed correctly. Haha !!! M_name = "xxxx";} QString name () const {return m_name;} void name (const QString & name) {m_name = name;} private: QString m_name; QString m_id;}; class Test: public QObject {Q_OBJECTpublic: Test () {qregistercmdype <Student> ("Student"); connect (this, SIGNAL (sendStu (Student )), this, SLOT (getStu (Student); //, Qt: QueuedConnection);} private slots: void getStu (const Student & stu) {qDebug () <QThread:: currentThreadId () <"<stu. name ();} public: void printStu (const Student & stu) {emit sendStu (stu);} private: signals: void sendStu (const Student & stu );}; class MyThread: public QThread {Q_OBJECTpublic: MyThread (Test * test): m_test (test) {} protected: void run () {qDebug () <"non main thread" <QThread: currentThreadId () <'\ n'; Student stu ("aaa", "213 "); // transmit the m_test-> printStu (stu); stu. name ("bbb"); qDebug () <"I have reset student name \ n";} private: Test * m_test ;}; # endif // TK_HPP

Source file:

#include <QCoreApplication>#include"tk.hpp"int main(int argc, char *argv[]){    QCoreApplication a(argc, argv);    Test test;    MyThread mythread(&test);    mythread.start();    return a.exec();}

The execution output is:


We can see that Qt is indeed a replication error.



If you delete the copy constructor in Student, the output will be:


We can see that a Student has been copied inside Qt, so even if the name of Student is modified by the thread, it will not be affected.


Delete qregisterpolicype <Student> ("Student") in the Test constructor "). The following error occurs during running:



It is estimated that Qt will determine in the emit Implementation whether the thread sending the signal is the main thread. If not, check whether the parameters of signals/slots are metadata. If not, the system rejects sending signals. Non-metadata is insecure.

For basic types of C/C ++ and classes defined by Qt, you do not need to register them as metadata manually. Qt has helped us with these tasks.




In QT, two threads are used to operate the database. Currently, a global connection is established, and the subthread opens the database and writes the read data.

You need to open the connection separately

In the Qt example, how can we control threads outside the thread for inter-thread communication? The problem can be further solved. Thank you!

Don't talk about qt. I don't understand this. But let's talk about the essence of the thread. It is the same. It is not possible for two threads to simultaneously perform this operation, except for multi-core processors. I don't know if I can understand the post and send you mentioned, as if one is asynchronous and the other is synchronous. Thread A and thread B must have their own rest time and cannot be executed all the time. Otherwise, it will not be called A time segment. Time segments and messages are for cpu hardware. The signal of the specific conversion thread is completed by the cpu processor. Therefore, it is impossible for B to keep resting, and then A to wake up the processing function of B. It should be said that B always has a rest period, including running time, which is determined based on the cpu signal. When B is running, his message processing function can always receive messages, because the message can be temporarily stored in the memory, as to the decision based on the processing function, and then based on the incoming parameters (marked as post or send) to determine whether it is executed by the current thread, it is still executed by the sent thread. I personally understand. You are right ..

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.