Introduced
The Qtimer is a QT-band timer class, and the Qtimer runtime is dependent on the event loop, and in a nutshell, Qtimer is not available in a thread that does not turn on the event loop (EXEC () is not called). By analyzing the QT source, it is found that the call to Qtimer::start () only adds a timer object to the system's timer vector table, but the timer is not actually turned on. The timer must be opened after a series of calls starting with processevent (), which will process all the timer objects in the Timer vector table. The processevent () method is also constantly being called in the actual exec ().
Problem
You may encounter a resident thread in a project, run a dead loop that handles transactions, and it is not possible to use Qtimer directly in a dead loop to implement timing functions. My own project is to achieve the serial read and write time-out judgment, so need to use the timer.
Solve
The solution can be found on the web, and it works well, but there are problems. Let's talk about the idea first:
The timer object needs to run in a thread that turns on the event loop, so we can move it to a thread that has the event loop turned on by the Movetothread () method. Very happy, we quickly encapsulated a timer class, containing a Qtimer and Qthread object, directly using the Qthread object is because my QT version is 4.8.3,run () is not a pure virtual function, the event loop is turned on by default. The main code is as follows:
[CPP]View PlainCopyprint?
- #ifndef Qcustomtimer_h
- #define Qcustomtimer_h
- #include <QObject>
- #include <QTimer>
- #include <QThread>
- Class Qcustomtimer: Public qobject
- {
- Q_object
- Public
- explicit Qcustomtimer (Qobject *parent = 0);
- ~qcustomtimer ();
- Private
- Qtimer *m_ptimer; //Timer Object
- Qthread *m_ptimerthread; //Timer dependent thread
- Signals:
- void startsignal ( int nMsc); Turn on the timer signal
- void Stopsignal (); //Stop timer signal
- void TimeOut (); //Timer trigger, external need to connect this signal
- void Deletelater (); //Delay removing timer signal
- Public Slots:
- void OnTimer (); //Object internal timing trigger slot function, trigger signal to external launch timer
- Public
- void Starttimer ( int nMsc); //Turn on timer
- void Stoptimer (); //Off timer
- void Deletelater (); //Delay Delete Timer object
- };
- #endif//Qcustomtimer_h
[CPP]View PlainCopy print?
[CPP]View PlainCopyprint?
- #include "Qcustomtimer.h"
- Qcustomtimer::qcustomtimer (Qobject *parent):
- Qobject (parent)
- {
- M_ptimer = New Qtimer (0);
- M_ptimer->setsingleshot ( true); Single-shot triggering
- M_ptimerthread->start ();
- M_ptimer->movetothread (M_ptimerthread); //Change the thread on which the timer runs
- Connect (M_ptimer, SIGNAL (), this , SLOT (OnTimer ()), Qt::D irectconnection); Timer Event Trigger slot
- Connect (this , SIGNAL (startsignal (int)), M_ptimer, SLOT (Start ( int)), qt::blockingqueuedconnection); Connect timer start slot function, not "Direct connect"
- Connect (this , SIGNAL (Stopsignal ()), M_ptimer, SLOT (Stop ()), qt::blockingqueuedconnection); Connect timer close slot function, not "Direct Connect"
- Connect (this , SIGNAL (Deletelater ()), M_ptimer, SLOT (Deletelater ())); Delete the Timer object that is located in the thread, inserting an event with deferred deletion
- }
- Qcustomtimer::~qcustomtimer ()
- {
- Stoptimer ();
- Deletelater ();
- }
- void Qcustomtimer::ontimer ()
- {
- Emit TimeOut (); //TX Timer trigger Signal
- }
- void Qcustomtimer::starttimer (int nMsc)
- {
- Emit startsignal (NMSC); //Shangzi in-thread timer Send on timer signal
- }
- void Qcustomtimer::stoptimer ()
- {
- Emit stopsignal (); ///Shangzi timer in thread to send stop timer signal
- }
- void Qcustomtimer::D eletelater ()
- {
- Emit Deletelater (); //Shangzi thread's event loop inserts a deferred delete event
- }
Actually in the initial use, no problem, the timer triggers normally. However, when Qcustomtimer objects are created and refactored very frequently, problems such as crashes occur. More ashamed, this problem bothers me for a long time, although finally solved the problem, but I still do not know what causes, if there is Daniel know, please you must tell me!!
Here's what the code says:
1. When the Movetothread () method is called, the timer object belongs to the child thread, and if it is released, it will either insert the Deletelater () time-lapse Delete event in the document or the object is freed before the run () function returns. The code above uses pointers, uses the form of member variables without pointers, and I try, the program still crashes.
2. To say a little more, is the program crashes basically a few hours to collapse, the program error "pure virtual function is called", for this clue Google a lot of information, but did not find a response plan.
3. Speculation or in the case of high-frequency use, the timer object and the destruction of the thread object has a problem, and deletelater () can not be resolved.
My solution, in fact, is not rigorous, because I did not pinpoint the bug. I changed the thread object to static, that is, to remove the thread object's destruction, only need to properly deconstruct the timer object, this is Deletelater () has the effect. The code is as follows:
[CPP]View PlainCopy print?
- #ifndef Qcustomtimer_h
- #define Qcustomtimer_h
- #include <QObject>
- #include <QTimer>
- #include <QThread>
- Class Qcustomtimer: Public qobject
- {
- Q_object
- Public
- explicit Qcustomtimer (Qobject *parent = 0);
- ~qcustomtimer ();
- Private
- static Qthread *m_ptimerthread; //Timer dependent thread
- Qtimer *m_ptimer; //Timer Object
- Signals:
- void startsignal ( int nMsc); Turn on the timer signal
- void Stopsignal (); //Stop timer signal
- void TimeOut (); //Timer trigger, external need to connect this signal
- void Deletelater (); //Delay removing timer signal
- Public Slots:
- void OnTimer (); //Object internal timing trigger slot function, trigger signal to external launch timer
- Public
- void Starttimer ( int nMsc); //Turn on timer
- void Stoptimer (); //Off timer
- void Deletelater (); //Delay Delete Timer object
- };
- #endif//Qcustomtimer_h
[CPP]View PlainCopyprint?
- #include "Qcustomtimer.h"
- Static thread member pointer initialization
- qthread* qcustomtimer::m_ptimerthread = NULL;
- Qcustomtimer::qcustomtimer (Qobject *parent):
- Qobject (parent)
- {
- if (m_ptimerthread = = NULL)
- {
- //This decision branch relies on QT to initialize static member pointer variables to NULL, not a good practice
- //But if there are other global variables in the project and have dependencies, then it should be the case.
- //Ensure that the Qcustomtimer class does not have dependencies with other global variables and can be initialized outside of the class, which is better
- M_ptimerthread = new Qthread;
- }
- M_ptimer = New Qtimer (0);
- M_ptimer->setsingleshot ( true); Single-shot triggering
- M_ptimerthread->start ();
- M_ptimer->movetothread (M_ptimerthread); //Change the thread on which the timer runs
- Connect (M_ptimer, SIGNAL (), this , SLOT (OnTimer ()), Qt::D irectconnection); Timer Event Trigger slot
- Connect (this , SIGNAL (startsignal (int)), M_ptimer, SLOT (Start ( int)), qt::blockingqueuedconnection); Connect timer start slot function, not "Direct connect"
- Connect (this , SIGNAL (Stopsignal ()), M_ptimer, SLOT (Stop ()), qt::blockingqueuedconnection); Connect timer close slot function, not "Direct Connect"
- Connect (this , SIGNAL (Deletelater ()), M_ptimer, SLOT (Deletelater ())); Delete the Timer object that is located in the thread, inserting an event with deferred deletion
- }
- Qcustomtimer::~qcustomtimer ()
- {
- Stoptimer ();
- Deletelater ();
- }
- void Qcustomtimer::ontimer ()
- {
- Emit TimeOut (); //TX Timer trigger Signal
- }
- void Qcustomtimer::starttimer (int nMsc)
- {
- Emit startsignal (NMSC); //Shangzi in-thread timer Send on timer signal
- }
- void Qcustomtimer::stoptimer ()
- {
- Emit stopsignal (); ///Shangzi timer in thread to send stop timer signal
- }
- void Qcustomtimer::D eletelater ()
- {
- Emit Deletelater (); //Shangzi thread's event loop inserts a deferred delete event
- }
What needs to be explained is the initialization position of the static thread, and my approach is a stopgap, because the other global variables in the project have a dependency on the Timer class, which can only be done. The design pattern still needs to be studied well to avoid these bad designs.
The above is the complete code, if there are bugs or problems, welcome to my message!!
http://blog.csdn.net/u013709994/article/details/22175919
Using Qtimer in a thread that does not turn on the event loop (the Qthread::run function has an event loop, creating threads in the constructor is a very interesting thread usage) good