Qt As a C cross-platform GUI system, QT can provide powerful functions to the user to construct a graphical user interface. In order to meet the needs of users to construct complex graphics interface systems, QT provides a wealth of multi-threaded programming support. Starting from version 2.2, QT is mainly supported by multi-threaded programming from the following three aspects: First, construct some basic and platform-independent thread classes; Second, submit the THREAD-SAFE mode for user-defined events; three, many Synchronization mechanism between threads, such as semaphors, global locks. These provide users with great convenience. However, in some cases, the usage timer mechanism can be easily achieved more easily than multi-threading mechanisms that use QT itself, but also avoids unsafe phenomenon. This article not only discusses the multi-threaded support mechanism in QT, but also focuses on the method of simulating multi-threaded programming using the timer mechanism.
1, the system supports multithreaded programming
Different platforms are different from QT multi-thread support. When the user installs the QT system on the Windows operating system, the thread support is an option of the compiler, including the compilation file of different kinds of compilers in the mkfiles subdirectory of QT, where the file with the -MT suffix is supported Thread.
In the UNIX operating system, the thread support is added by adding the -Thread option when running the configure script file. The installation process will create a separate library, which is the libqt-mt, so when you want to support multi-thread programming, you must link to the library link (link option is -lqt-mt) instead of link with the usual QT library (-lqt).
In addition, no matter what platform, you need to define macro Qt_thread_support (adding compile options -dqt_thread_support) when adding thread support. In the Windows operating system, this is usually achieved in the QConfig.h file. In the UNIX system, it is usually added in the relevant Makefile file.
2, thread class in QT
The most important class associated with the thread in the QT system is of course QThread class, which provides a variety of methods for creating a new thread and controlling threads. Threads are executed by qthread :: run () overload function, this is very similar to the thread class in the Java language. In the QT system, a GUI primary event thread is always running, this primary thread gets an event from the window system and distributes them to each component. In the QThread class, there is also a method of submitting an event to an object from a non-main event thread, that is, the qthread :: postEvent () method, which provides an event submission process of a Thread-Safe in the QT. The submitted event is placed in a queue, then the GUI main event thread is awakened and sent this event to the corresponding object, which is the same as the general window system event processing process. It is worth noting that when the event processing is called, it is called in the main event thread, not in the thread that calls the QThread :: POSTEVENT method. For example, the user can force another thread to redraw a designated area from one thread:
Qwidget * mywidget;
Qthread :: POSTEVENT (MyWidget, New QPaintevent (QRECT (0,0,100,100));
However, only one thread class is not enough. To write a multi-threaded program, two different threads need to implement mutex access to a common data, so QT also provides QMuteX classes, and a thread is in accessing critical data. It is necessary to lock, at which time other threads are unable to lock the critical data simultaneously until the top thread releases the critical data. In this way, atomic operations for critical data can be achieved. In addition, some mechanisms require a thread in the waiting state to be awakened in a particular case. The QWAITCONDITION class provides this feature. When a specific event occurs, QWaitCondition wakes up all threads waiting for the event or wake up any of the selected threads.
3. Application of user-defined events in multi-threaded programming
In the QT system, many types of events are defined, such as timer events, mouse movements, keyboard events, window control events, etc. Typically, events come from the underlying window system, QT's primary event loop function gets these events from the system's event queue and converts them to QEvent, and then transmits the corresponding QObjects object.
In addition, in order to meet the needs of users, the QT system also provides a QCUSTOMEvent class for user-defined events that can be sent to each other with qthread :: poste () or qapplication :: postevent () A control or other qbject instance, and the subclass of the QWidget class can easily receive these custom events via the QWIDGET :: CustomEvent () event handler. It should be noted that the QCUSTOMEVENT object has a type identifier ID in the creation to define the event type, in order to avoid conflicts with the Event type conflict defined by the QT system, the ID value should be greater than the enumerated type qEvent :: type "" User value.
In the following example, how to use the user-defined event class in multi-threaded programming.
The Usevent class is a user-defined event class whose event identifies 346798, apparently does not conflict with the system type defined by the system.
Class Userevent: Public QCustomEvent // User-defined event class
{
PUBLIC:
Userevent (QString S): QCUSTOMEVENT (346798), SZ (s) {;
QString str () const {return sz;}
Private:
QString SZ;
}
The UserThread class is subclass inherited by the QThread class, in which the most important thing is to define the startup function of the thread, which is created in this function. A user-defined event useEREVENT and uses the POSTEVENT function of the QThread class to submit the event to the corresponding receiving object.
Class useERTHREAD: PUBLIC Qthread // User-defined thread class
{
PUBLIC:
Userthread (QObject * R, QMutex * M, QWaitcondition * C);
QObject * Receiver;
}
Void UseRead :: Run () // Thread class start function, created a user-defined event in this function
{Userevent * re = new userevent (resultString);
Qthread :: POSTEVENT (Receiver, RE);
}
The UserWidget class is a subscler that the user-defined Qwidget class used to receive custom events. This class creates a new thread RECV (UserThread class) using the slotgo () function, when receiving the corresponding custom event (ie the ID is 346798) When the event is processed using the CustomEvent function. Void UserWidget :: Slotgo () // User Defines Controls Member Functions
{mutex.lock ();
IF (! RECV)
Recv = New UserThread (this, & mutex, & condition);
RECV-> Start ();
Mutex.unlock ();
}
Void UserWidget :: CustomEvent (QCUSTOMEVENT * E) // User Custom Event Processing Function
{IF (e-> type () == 346798)
{
Userevent * re = (uservent *) e;
Newstring = re-> Str ();
}
}
In this example, a new thread usrthread is created in the UserWidget object, and the user can use this thread to implement some periodic processing (such as receiving the underlying message, etc.), once the specific condition is met, a user-defined event is submitted. When the UserWidget object receives the event, the corresponding processing can be made as needed, in general, the UserWidget object can perform some routine processing normally, and is completely unaffected by the underlying message.
4. Implement multi-threaded programming using the timer mechanism
In order to avoid problems with multi-thread programming in the QT system, you can also use the timer mechanisms provided in the system to implement similar functions. The timer mechanism will be serially serially connected to the incident, simplify the processing of concurrent events, thereby avoiding the emergence of Thread-Safe.
In the following example, there are several objects that need to receive the underlying message (can communicate with the process of Socket, FIFO, etc.), and the message is randomly received, requiring a GUI main thread to receive a message. When the message is received, the main thread initializes the corresponding object, and returns, the main thread can always update the interface display and receive the message from the outside world, and achieve the control of multiple objects; on the other, each object The GUI main thread is required after processing the message. For this problem, you can use the method of user-defined events in Section 3. Install an event filter in the main thread to capture custom events from each object, and then issue a signal calling one of the main thread. Slot function.
In addition, similar functions can also be implemented using the timer mechanism in the QT, but do not worry about the Thread-Safe problem. The following is the relevant code part:
Create and launch the timer in the user-defined Server class, and use the Connect function to turn the timer timeout with the read device file data:
Server :: Server (Qwidget * Parent): Qwidget (PARENT)
{
Readtimer = new QTIMER (this); // Create and start the timer
Connect (READTIMER, SIGNAL (Timeout ()), this, slot (SlotReadFile ()))); / / Call function slotreadfile read file whenever timer timeout
Readtimer-> Start (100);
}
The SlotReadFile function is responsible for reading data from the file at the timer timeout, then restart the timer:
INT Server :: slotreadFile () // Message Read and Processing Function {
Readtimer-> stop (); // Temporarily stop timer
Ret = read (file, buf); // read files
IF (RET == NULL)
{ReadTimer-> Start (100); // Restart the timer when there is no new message
Return (-1);
}
Else
Distribute messages to each corresponding object processing according to content in BUF ...
Readtimer-> Start (100); // Restart Timer
}
In this procedure, the device file specified by the user is read by means of a similar rotation, and the information is transmitted to the respective corresponding objects based on the read data content. Users can create a Server class in their own GUI main thread to help implement the underlying messaging process, and itself can still handle problems such as interface display. When each object is completed, the process of continuing periodic reading of the underlying device file is proceeded by restarting the timer. Of course, this method is suitable for the processing time of each object to the event, and the frequency of the underlying device is relatively slower. In this case, the above method can fully meet the needs of the user, and avoid processing some complicated issues related to the thread.
Of course, using timer mechanisms to achieve multi-threaded programming has certain limitations in certain aspects, how to implement multi-threaded programming, how to write efficient code, and to further study and discuss developers.
Reference
(1) Qt official document http://doc.trolltech.com/3.2/index.html
(2) Qt source code: qthread, qcustomet, qtimer.
(3) Advanced Programming in The UNIX Environment, W. Richard Stevens.
Continued Xin April 2004 www-128.ibm.com/developerWorks
About the author, Continuation: Contact XXIN76@hotmail.com.