青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

春暖花開
雪化了,花開了,春天來了
posts - 149,comments - 125,trackbacks - 0

調用SendMessage 產生死鎖的問題分析

http://www.shnenglu.com/woaidongmao/archive/2008/12/17/69696.html

 

 

()       SendMessage 的工作機制

首先我要先簡要的說明一個和這個話題有關系的消息處理機制:

    Window操作系統當中,窗口時屬于所在Thread的也就是說 你這個窗口在那個Thread 當中Create 的那么你這個窗口就屬于那個Thread。同時窗口的消息處理函數也都會在這個Thread 當中被執行的。(不要問為什么 Window 就是這么設計的 嘿嘿)

 

在講死鎖之前我們先把SendMessage的工作機制搞清楚;

SendMessage 發送出來的消息 到底進入不進入消息隊列,有人說進入,有人說不進入,其實都是錯誤的,確切的說是有時進入,有時不進入。那么什么時候進入,什么時候不進入呢? 我們舉一例子來說:假如在 Thread A 中有一個 窗口W1,那么 在 Thread A 中像 W1 SendMessage 一個消息,那么這個消息將不會被放入消息隊列,而是直接調用了W1的消息處理函數來直接處理了這個消息。這是不被放入隊列的情況;假如現在又多了一個Thread B ,那么在 Thread B 中 像 W1 SendMessage 發送消息 這個時候 W1 將被放入到 Thread A 的消息隊列當中,這些Thread A 中的消息循環的GetMessage Get到這個消息 并處理之。 這就是進入消息隊列情況;根據在哪里我們來看看我的測試結果:

 

測試1我創建了一個無DOC/View 之支持的單文檔工程:

我在CMainFrame添加如下代碼:

        BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)

               ON_WM_CREATE()

               ON_WM_SETFOCUS()

               ON_MESSAGE(WM_USER + 100,OnMy)

ON_MESSAGE(WM_USER + 200,OnMy2)

END_MESSAGE_MAP()

 

LRESULT CMainFrame::OnMy(WPARAM wParam,LPARAM lParam)

{

             int i = 0;

             return TRUE;

}

 

LRESULT CMainFrame::OnMy2(WPARAM wParam,LPARAM lParam)

{

             int i = 2;

             return TRUE;

}

然后我再 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 的最后 加入了一行代碼:

SendMessage(WM_USER + 100,0,0);

 

此主題相關圖片如下:
clip_image002

然后直接 F5 運行程序 等到 程序停止在斷點上,我們看看Call Stack 的調用順序:


clip_image001
此主題相關圖片如下:
clip_image003

 

然后 我又將 SendMessage 改成:

PostMessage(WM_USER + 100,0,0);

然后直接 F5 運行程序 等到 程序停止在斷點上,我們再看看Call Stack 的調用順序:


clip_image001
此主題相關圖片如下:
clip_image004

通過這2 Call Stack 大家可以很清楚的看到,執行SendMessage的時候,是直接調用了 AfxWndProcBase 這個 消息處理函數(MFC 通過HOOK 將所有窗口的處理函數都重定向到這個 函數上了,AfxWndProcBase()不明白的自己去看《MFC深入淺出》),大家可以很清楚的看到,在SendMessage AfxWindProcBase 之間根本沒有調用CWinApp::Run() ,也就是說從SendMessage 到執行OnMy()根本沒有通過程序的主消息循環的GetMessage Run 內部好像用的PeekMessage記不清楚了)取消息。那么有人會問,SendMessage的內部就不會先發消息放入隊列再通過GetMesssage把消息取出來了嗎?答根本沒必要那樣做,那是脫褲子放P多此一舉。

從這個測試例子的結果我判定SendMessage Thread A 中向 W1

SendMessage 的消息根本不進入消息隊列。

測試2那么什么時候進入隊列呢我來看看這個例子

沿用上面那個例子的代碼我將 OnCreate 中的 SendMessage PostMessage 都刪除掉。然后加入如下代碼:

//Thread Proc

UINT ThreadProc(LPVOID lParam)

{

             CMainFrame * v_pFrameWnd = (CMainFrame *)lParam;

             if(v_pFrameWnd)

             {

                v_pFrameWnd->SendMessage(WM_USER + 100,0,0);

             }

             return 0;

}

并且 在 OnCreate 種加入如下代碼:

AfxBeginThread(ThreadProc,this);

然后F5 運行 等待程序停在斷點處,看Call Stack 如下:


clip_image001
此主題相關圖片如下:
clip_image005

我們發現這個 Call Stack 就和剛才那個PostMessage Call Stack 是一樣的 這個 WM_USER + 100 消息是通過 Run 內部的 GetMessage 取出來的 。所以我斷定:

 

Thread B 中向W1 SendMessage 發送消息 ,消息是放入了 Thread A 的消息隊列中。由于SendMessage的特性只有當消息被執行完畢才能夠返回,所以Thread B 中的SendMessage 要等 Thread A 當中消息執行完畢后才能夠返回。

()       SendMessage 產生的 死鎖問題

Thread 死鎖肯定是發生在2Thread 之間,AB B A,就產生了死鎖。大家看了上面測試之后一定會發現,SendMessage 的死鎖和上面的第二個例子有關系,也就是 說 通過 Thread B W1 發送消息的時候又可能會產生死鎖。

 

 

那么死鎖 何時產生呢 ?通過上面的例子我們知道了 如果Thread B W1 SendMessage一個消息,那么 Thread B 的這個SendMessage 就要等 Thread A 的隊列中的 消息執行完畢才能夠返回,如果在 Thread B SendMessage 的同時 Thread A 等待 Thread B 中的某一處理完畢才能夠繼續處理消息的話,那么這個時候就發送了死鎖。

 

我們繼續以測試來說明:

測試3

    首先在 CMainFrame中加入一個 成員變量:m_bThreadExit Public

    我們將 UINT ThreadProc(LPVOID lParam) 加入一樣代碼如下:

       UINT ThreadProc(LPVOID lParam)

{

          CMainFrame * v_pFrameWnd = (CMainFrame *)lParam;

          if(v_pFrameWnd)

          {

             v_pFrameWnd->SendMessage(WM_USER + 100,0,0);

          }

          v_pFrameWnd->m_bThreadExit = TRUE;

          return 0;

}

然后再 OnCreate 當中添加如下代碼:

                             m_bThreadExit = FALSE;

          AfxBeginThread(ThreadProc,this);

 

          while(TRUE)

          {

             if(m_bThreadExit)

                break;

             Sleep(55);

}

 

 OK 編譯 F5 運行 發現程序 進入無響應狀態,好這時我么讓程序 暫停:

看看 2Thread Call Stack 都停在那里了?

Main Thread如下:

 

clip_image001此主題相關圖片如下:
clip_image006

在看看 另一個線成:



clip_image001
此主題相關圖片如下:
clip_image007

這會 是不是 很明了了

MainThread 停在 循環內 等待 m_bThreadExit True,而 另一個線成 則等待 MainThread 處理完畢 WM_USER + 100 這個消息,結果你等我,我等你,死了。。。。

()       處理辦法

1 針對上面的例子 我們 可以通過 把SendMessage 改成 PostMessage 的方法來放棄等待。 這樣就解決了

2 有些時候 第1種方法不符合要求比如下面這中情況

UINT ThreadProc(LPVOID lParam)

{

          CMainFrame * v_pFrameWnd = (CMainFrame *)lParam;

          if(v_pFrameWnd)

 

          {

          v_pFrameWnd->SetWindowText("lvyang");

          }

          v_pFrameWnd->m_bThreadExit = TRUE;

          return 0;

}

這里面的CWnd::SetWindowText里面實際上調用的是::SetWindowText 而::SetWindowText 里面有調用 SendMessage 發送一個消息給CWnd 的窗口 ,因為::SetWindowText 內部的我們沒有辦法來修改,那我只能去修改 MainThread 當中的 While 循環了。

 

那如何修改呢? ThreadProc 當中 SetWindowText之所以被諸塞,就是因為 它向 MainThread SendMessage 的消息沒有得到處理,那么我們讓他處理的不就OK了嗎?好那我們就讓他處理,代碼如下:

MSG msg;

       while(TRUE)

       {

          if(m_bThreadExit)

             break;

          if(::PeekMessage(&msg,NULL,NULL,NULL,PM_NOREMOVE))

          {

             if(::GetMessage(&msg,NULL,NULL,NULL))

             {

                if(!PreTranslateMessage(&msg))

                {

                   ::TranslateMessage(&msg);

                   ::DispatchMessage(&msg);

                }

             }

          }

          Sleep(55);

}

終于搞完了

posted on 2008-12-19 08:42 Sandy 閱讀(1074) 評論(2)  編輯 收藏 引用 所屬分類: 雜項學習

FeedBack:
# re: 調用SendMessage 產生死鎖的問題分析
2009-10-16 20:45 | ahenl
SendMessage不放進隊列中的,msdn寫得很清楚:

1. 同線程時,立即執行窗口過程:If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine.

2. 不同線程時, 待接收線程從隊列中取消息時執行窗口過程,并沒有說消息放進隊列中,只說明了處理時機: If the specified window was created by a different thread, the system switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code.  回復  更多評論
  
# re: 調用SendMessage 產生死鎖的問題分析
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美国产精品人人做人人爱| 亚洲精品综合久久中文字幕| 亚洲精品欧美| 欧美视频在线观看| 欧美福利电影网| 国产中文一区二区| 亚洲一级一区| 亚洲小说欧美另类社区| 欧美国产日韩一区二区| 免费成人你懂的| 国产自产2019最新不卡| 亚洲在线观看免费视频| 亚洲一区二区免费| 欧美无砖砖区免费| 99国产一区二区三精品乱码| 亚洲欧洲精品一区二区三区不卡 | 亚洲午夜电影网| 欧美高清视频一区| 欧美激情亚洲综合一区| **欧美日韩vr在线| 久久久综合网站| 六月婷婷久久| 在线日本成人| 久久婷婷丁香| 欧美韩国日本一区| 亚洲精品午夜精品| 欧美精品久久久久久久久老牛影院| 欧美 日韩 国产一区二区在线视频| 国产主播一区二区三区| 久久国产精品一区二区| 麻豆精品91| 亚洲国产精品一区制服丝袜 | 欧美日韩国产精品专区| 亚洲九九爱视频| 一区二区三区视频在线| 欧美视频中文一区二区三区在线观看 | 亚洲美女视频| 欧美三级中文字幕在线观看| 一个人看的www久久| 亚洲欧美日韩国产成人| 国产精品一区在线观看你懂的| 亚洲欧美日韩精品| 久久在线视频在线| 亚洲激情黄色| 欧美日韩中文在线观看| 亚洲欧美日韩在线| 欧美第一黄色网| 日韩一区二区精品葵司在线| 国产精品盗摄久久久| 午夜精品在线看| 欧美成人中文字幕在线| 亚洲调教视频在线观看| 国产一区二区三区久久悠悠色av| 久久人人爽人人| 亚洲久色影视| 久久久久久**毛片大全| 91久久夜色精品国产九色| 欧美视频网址| 久久久亚洲欧洲日产国码αv| 亚洲欧洲一区| 久久久久www| 亚洲乱码精品一二三四区日韩在线| 国产精品h在线观看| 久久精品视频亚洲| 一本一本大道香蕉久在线精品| 久久国产手机看片| 99在线|亚洲一区二区| 国产一区二区av| 欧美日韩一视频区二区| 久久久久国产一区二区三区四区 | 亚洲国产欧美日韩精品| 午夜一区二区三区在线观看| 亚洲高清一区二区三区| 国产精品色在线| 欧美精品三级| 久久综合中文| 欧美亚洲综合另类| 日韩午夜高潮| 亚洲福利一区| 久久这里只有| 久久久国产精品亚洲一区 | 亚洲精品美女久久7777777| 国产一区二区三区成人欧美日韩在线观看| 欧美电影美腿模特1979在线看| 亚洲欧美国产不卡| 一区二区电影免费观看| 欧美激情免费在线| 久久综合久久久久88| 欧美一区网站| 香蕉久久夜色精品国产| 在线亚洲伦理| 一本色道久久加勒比精品| 136国产福利精品导航网址| 国产私拍一区| 国产精品综合不卡av| 欧美午夜一区二区三区免费大片| 免费亚洲一区二区| 久久一区视频| 久久在线播放| 久热成人在线视频| 久久亚洲一区二区| 久热精品视频在线| 老妇喷水一区二区三区| 久久久久**毛片大全| 欧美专区一区二区三区| 欧美一区二区女人| 久久爱www.| 久久手机免费观看| 久久综合色一综合色88| 久久一区二区精品| 你懂的亚洲视频| 蜜臀久久99精品久久久久久9| 久久综合色播五月| 欧美bbbxxxxx| 欧美日韩国产色站一区二区三区| 欧美另类变人与禽xxxxx| 欧美成va人片在线观看| 欧美精彩视频一区二区三区| 欧美日韩国产亚洲一区| 欧美视频不卡| 国产日韩欧美一二三区| 韩国女主播一区| 亚洲激情成人在线| 一区二区欧美日韩视频| 亚洲自拍电影| 久久久.com| 免费在线观看一区二区| 亚洲激精日韩激精欧美精品| 亚洲精品一区二区三| 亚洲视频一区二区| 欧美在线综合| 欧美国产精品人人做人人爱| 国产精品白丝黑袜喷水久久久| 国产精品永久在线| 亚洲国产高清在线观看视频| 一区二区不卡在线视频 午夜欧美不卡在| 亚洲色图在线视频| 久久精品国内一区二区三区| 欧美成人一区二区| 一区二区三区精品| 久久久蜜桃精品 | 欧美 日韩 国产精品免费观看| 欧美成人蜜桃| 国产精品拍天天在线| 伊人精品久久久久7777| 亚洲免费观看| 欧美在线国产精品| 欧美激情一区二区三区不卡| 亚洲视频一区二区| 老司机67194精品线观看| 欧美午夜宅男影院| 亚洲第一网站| 欧美在线欧美在线| 亚洲美女电影在线| 久久精品视频免费播放| 欧美色图首页| 亚洲国产精品欧美一二99| 亚洲欧美成aⅴ人在线观看| 欧美刺激性大交免费视频| 亚洲综合色视频| 欧美日韩成人激情| 影院欧美亚洲| 欧美中文字幕在线播放| 日韩网站在线| 欧美二区视频| 一区二区亚洲精品| 欧美一区二区三区婷婷月色| 亚洲精品久久久久久久久| 欧美一区二区三区久久精品茉莉花 | 欧美一区二区三区婷婷月色| 欧美日本不卡高清| 最新国产の精品合集bt伙计| 欧美一区综合| 亚洲无毛电影| 欧美日韩日本视频| 亚洲欧洲一区二区三区在线观看 | 卡通动漫国产精品| 国产亚洲综合性久久久影院| 一区二区三区产品免费精品久久75| 免费久久99精品国产自| 欧美亚洲视频一区二区| 国产精品久久久久久久午夜| 一区二区免费看| 欧美激情在线免费观看| 久久免费视频观看| 精品成人国产| 免费成人黄色片| 久久日韩精品| 亚洲国产电影| 欧美激情视频网站| 欧美成人精品一区二区三区| 亚洲第一精品福利| 欧美国产1区2区| 免费国产一区二区| 亚洲毛片av在线| 91久久久久久久久久久久久| 欧美高清视频一区二区三区在线观看| 亚洲国产99精品国自产| 欧美激情精品久久久久久大尺度 | 91久久精品美女高潮|