看到一篇blog,http://blog.pfan.cn/yuqiexing/40732.html
/////////////////
CxxxDlg::OnTimer(UINT nIDEvent)
{
static int i = 0,j;
j = i++;
if (i==2) KillTimer(nIDEvent);
MessageBox("!");
i++;
CString str;
str.Format("%d,%d ",j,i);
::OutputDebugString(str);
}
以上代碼在執行的時候,會彈出2個messagebox。很多人都有1個疑問,那就是當第一個消息框彈出的時候,應該相當於是模態對話框,怎麼還會第二次進入OnTimer,並且再次彈出messagebox?
他的解釋是:
原來,當你在主消息循環的消息處理函數中彈出一個模態對話框,他阻塞了主消息循環,理論上,這時可以把主窗口關閉了!但是因為這個彈出的模態對話框還在, 它阻塞了winmain這個主消息循環,實際上你是關不掉的。注意,阻塞的實際意思是說:消息被模態對話框處理了,而沒有傳到後面的父窗口。而每次彈出對 話框,都是由最上層的那個消息框掌握著消息循環,其他的消息循環被阻塞了。
所以,上面代碼運行的情況是:
(1)彈出第一個messagebox,然後後續代碼暫停執行。
(2)第二次進入OnTimer
(3)彈出第二個messagebox接替消息循環,第一個messagebox禁用。後續代碼暫停執行。
(4)用戶點擊第二個messagebox。此時顯示結果,i = 3,j=1;再次,點擊第一個messagebox,此時顯示結果,i=4 ; j=0
(測試顯示應該是: i =4, j=1);
我的疑問,當彈出第一個messagebox後,主消息循環被阻塞,OnTimer中後續代碼暫停執行,也就是說OnTimer沒有返回,是這樣嗎?那麼 怎麼能夠第二次進入OnTimer呢?這樣的話一個函數還沒有返回又第二次進入執行,有可能造成衝突啊,事實上的確是第二次進入OnTimer了。
以上說明:OnTimer沒有返回時,間隔時間到,可以重複進入該函數。又做了個測試
double fun(double i)//執行時間較長,大於100ms
{
double t = 1;
for(;i <100000000;i++)
{
t = t*i/(i+1);
}
return t;
}
void CMainFrame::OnTimer(UINT nIDEvent)
{
static double i=0,j=0;
fun(i);
j++;
if(j == 0)
{
MessageBox("jjjjjjjjjjjjjjjjjjjjjjjjjj");
}
CFrameWnd::OnTimer(nIDEvent);
}
在主窗口初始化時定義定時器
SetTimer(1,100,NULL);
結果沒有任何messagebox輸出;
也就是說在fun()正在執行,沒有返回時,間隔時間到,並沒有再次進入OnTimer(),而是一直等到fun()返回[b]。[/b]
這個和前一個測試有什麼區別?為什麼能導致不同的結果呢?
---------------------------------------------------------------------
樓主首先要明白,第二次進入OnTimer不需要在第一次退出OnTimer後才能發生,函數重入是非常常見的事情,尤其是有模態對話框的情況,wltg解釋的很好,希望你能懂
/////////////////
CxxxDlg::OnTimer(UINT nIDEvent)
{
static int i = 0,j;
j = i++;
if (i==2) KillTimer(nIDEvent);
MessageBox("!");
i++;
CString str;
str.Format("%d,%d ",j,i);
::OutputDebugString(str);
}
以上代碼在執行的時候,會彈出2個messagebox。很多人都有1個疑問,那就是當第一個消息框彈出的時候,應該相當於是模態對話框,怎麼還會第二次進入OnTimer,並且再次彈出messagebox?
他的解釋是:
原來,當你在主消息循環的消息處理函數中彈出一個模態對話框,他阻塞了主消息循環,理論上,這時可以把主窗口關閉了!但是因為這個彈出的模態對話框還在, 它阻塞了winmain這個主消息循環,實際上你是關不掉的。注意,阻塞的實際意思是說:消息被模態對話框處理了,而沒有傳到後面的父窗口。而每次彈出對 話框,都是由最上層的那個消息框掌握著消息循環,其他的消息循環被阻塞了。
所以,上面代碼運行的情況是:
(1)彈出第一個messagebox,然後後續代碼暫停執行。
(2)第二次進入OnTimer
(3)彈出第二個messagebox接替消息循環,第一個messagebox禁用。後續代碼暫停執行。
(4)用戶點擊第二個messagebox。此時顯示結果,i = 3,j=1;再次,點擊第一個messagebox,此時顯示結果,i=4 ; j=0
(測試顯示應該是: i =4, j=1);
我的疑問,當彈出第一個messagebox後,主消息循環被阻塞,OnTimer中後續代碼暫停執行,也就是說OnTimer沒有返回,是這樣嗎?那麼 怎麼能夠第二次進入OnTimer呢?這樣的話一個函數還沒有返回又第二次進入執行,有可能造成衝突啊,事實上的確是第二次進入OnTimer了。
以上說明:OnTimer沒有返回時,間隔時間到,可以重複進入該函數。又做了個測試
double fun(double i)//執行時間較長,大於100ms
{
double t = 1;
for(;i <100000000;i++)
{
t = t*i/(i+1);
}
return t;
}
void CMainFrame::OnTimer(UINT nIDEvent)
{
static double i=0,j=0;
fun(i);
j++;
if(j == 0)
{
MessageBox("jjjjjjjjjjjjjjjjjjjjjjjjjj");
}
CFrameWnd::OnTimer(nIDEvent);
}
在主窗口初始化時定義定時器
SetTimer(1,100,NULL);
結果沒有任何messagebox輸出;
也就是說在fun()正在執行,沒有返回時,間隔時間到,並沒有再次進入OnTimer(),而是一直等到fun()返回[b]。[/b]
這個和前一個測試有什麼區別?為什麼能導致不同的結果呢?
---------------------------------------------------------------------
樓主首先要明白,第二次進入OnTimer不需要在第一次退出OnTimer後才能發生,函數重入是非常常見的事情,尤其是有模態對話框的情況,wltg解釋的很好,希望你能懂
沒有留言:
張貼留言