My mind was suddenly confused about the problem, that is, how can a timer message be sent to a message queue when a thread with a timer installed is blocked? After the thread recovers from the blocking status, what is the status of the message queue? Does it contain multiple wm_timer messages? Or do I not receive the wm_timer message during the blocking period, or are multiple wm_timer messages to be delivered merged into one during the blocking period? (Similar to the wm_paint message ).
So I did a small experiment to verify this problem, and I found that the conclusion is the last case, that is, when the system is triggered to deliver wm_timer messages like a thread's message queue, if it finds that the same wm_timer message (with the same ID number) already exists in the message queue, it may discard delivery; otherwise, it will be shipped. This is consistent with the observed results, that is, the multiple timer messages that should be generated during the blocking process seem to be merged into one.
This experiment is like this. I install a 5-second timer for the UI thread (output in the window after receiving the timer message) and then initiate another thread, it takes 21 seconds to block the UI thread. Then observe the output of the UI thread. The effect is as follows:
We can draw a more intuitive image to explain the above output, as shown below:
In the figure, the Red Arrow is the timer message actually received by the UI thread, and the blue arrow is the time when the message should be generated during blocking. It can be seen that four wm_timer messages should be generated during the blocking period, but only one message is processed immediately after the thread recovers from the blocking status. After that, messages are sent regularly at specified intervals.
TheCodeAs follows:
Code_wm_timer_test
# Include " Stdafx. h "
# Include < String >
# Include " Resource. h "
Using Namespace STD;
Hinstance hinst;
StringM_msg;
IntBlocktime;
Lresult callback mydlgproc (hwnd hdlg, uint message, wparam, lparam );
//Test thread
DWORD winapi testthread (Void*Parg );
Int Apientry winmain (hinstance,
Hinstance hprevinstance,
Lpstr lpcmdline,
Int Ncmdshow)
{
// Todo: Place code here.
Hinst = Hinstance;
Dialogboxparam (hinst, makeintresource (idd_dialog1), null, (dlgproc) mydlgproc, 0 );
Return 0 ;
}
// Dialog Box
Lresult callback mydlgproc (hwnd hdlg, uint message, wparam, lparam)
{
Static Int B _timeron;
Static Int Timernum;
Switch (Message)
{
Case Wm_initdialog:
B _timeron = 0 ;
Timernum = 0 ;
Break ;
Case Wm_command:
{
Word CTL = Loword (wparam );
Switch (CTL)
{
Case Idok:
Case Idcancel:
Enddialog (hdlg, CTL );
Return True;
Case Idc_bt_settimer:
If (B _timeron)
{
Setdlgitemtext (hdlg, CTL, " Start Timer " );
Killtimer (hdlg, 1 );
}
Else
{
Setdlgitemtext (hdlg, CTL, " Stop Timer " );
Settimer (hdlg, 1 , 5000 , Null );
}
B _timeron ^ = 1 ; // Reverse (switch between 0 and 1)
Return True;
Case Idc_bt_startthread:
{
DWORD threadid;
Systemtime st;
Blocktime = 21000 ;
Char Line [ 128 ];
Handle hthread = Createthread (null, 0 ,
Testthread,
(Lpvoid) & Blocktime,
0 , // Run now
& Threadid
);
// sprintf (line, "thread: % LD start... \ r \ n ", threadid);
// m_msg + = line;
// setdlgitemtext (hdlg, idc_msg, m_msg.c_str ();
//Blocking main thread
Waitforsingleobject (hthread, infinite );
Closehandle (hthread );
Getlocaltime ( & St );
Sprintf (line, " % 02d: % 02d: thread: % LD exit... \ r \ n " , St. wminute, st. wsecond, threadid );
M_msg + = Line;
Setdlgitemtext (hdlg, idc_msg, m_msg.c_str ());
}
Return True;
}
}
Break ;
Case Wm_timer:
{
Systemtime st;
Char Text [ 96 ];
Getlocaltime ( & St );
Sprintf (text, " % 02d: % 02d wm_timer _ % 04ld \ r \ n " , St. wminute, st. wsecond, timernum );
Timernum ++ ;
M_msg = M_msg + Text;
Setdlgitemtext (hdlg, idc_msg, m_msg.c_str ());
}
Return True;
Case Wm_destroy:
Killtimer (hdlg, 1 );
Return True;
}
Return False;
}
// test thread
DWORD winapi testthread ( void * parg)
{< br> int * pblocktime = ( int * ) parg;
sleep ( * pblocktime);
return 0 ;< BR >}
Conclusion: according to the above observation, it can be considered that the timer message is similar to the draw message. During the process is blocked, multiple timer messages may be transparently merged into one message by the system. After the fault is restored from the blocking status, the timer will continue sending at the original interval.
Please note that do not think that all wm_timer will be generated strictly according to the response time (that is, do not think that a corresponding number will be generated ), do not think that each line will be processed at a certain time point (that is, the time it is processed depends on the running status of the thread, such as the delay caused by blocking ). It can be considered that all timer messages during the blocking period will be processed only once after the thread stops blocking.