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

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

調(diào)用SendMessage 產(chǎn)生死鎖的問題分析

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

 

 

()       SendMessage 的工作機(jī)制

首先我要先簡(jiǎn)要的說明一個(gè)和這個(gè)話題有關(guān)系的消息處理機(jī)制:

    Window操作系統(tǒng)當(dāng)中,窗口時(shí)屬于所在Thread的也就是說 你這個(gè)窗口在那個(gè)Thread 當(dāng)中Create 的那么你這個(gè)窗口就屬于那個(gè)Thread。同時(shí)窗口的消息處理函數(shù)也都會(huì)在這個(gè)Thread 當(dāng)中被執(zhí)行的。(不要問為什么 Window 就是這么設(shè)計(jì)的 嘿嘿)

 

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

SendMessage 發(fā)送出來的消息 到底進(jìn)入不進(jìn)入消息隊(duì)列,有人說進(jìn)入,有人說不進(jìn)入,其實(shí)都是錯(cuò)誤的,確切的說是有時(shí)進(jìn)入,有時(shí)不進(jìn)入。那么什么時(shí)候進(jìn)入,什么時(shí)候不進(jìn)入呢? 我們舉一例子來說:假如在 Thread A 中有一個(gè) 窗口W1,那么 在 Thread A 中像 W1 SendMessage 一個(gè)消息,那么這個(gè)消息將不會(huì)被放入消息隊(duì)列,而是直接調(diào)用了W1的消息處理函數(shù)來直接處理了這個(gè)消息。這是不被放入隊(duì)列的情況;假如現(xiàn)在又多了一個(gè)Thread B ,那么在 Thread B 中 像 W1 SendMessage 發(fā)送消息 這個(gè)時(shí)候 W1 將被放入到 Thread A 的消息隊(duì)列當(dāng)中,這些Thread A 中的消息循環(huán)的GetMessage 會(huì)Get到這個(gè)消息 并處理之。 這就是進(jìn)入消息隊(duì)列情況;根據(jù)在哪里我們來看看我的測(cè)試結(jié)果:

 

測(cè)試1我創(chuàng)建了一個(gè)無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);

 

此主題相關(guān)圖片如下:
clip_image002

然后直接 F5 運(yùn)行程序 等到 程序停止在斷點(diǎn)上,我們看看Call Stack 的調(diào)用順序:


clip_image001
此主題相關(guān)圖片如下:
clip_image003

 

然后 我又將 SendMessage 改成:

PostMessage(WM_USER + 100,0,0);

然后直接 F5 運(yùn)行程序 等到 程序停止在斷點(diǎn)上,我們?cè)倏纯?span>Call Stack 的調(diào)用順序:


clip_image001
此主題相關(guān)圖片如下:
clip_image004

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

從這個(gè)測(cè)試?yán)拥慕Y(jié)果我判定SendMessage Thread A 中向 W1

SendMessage 的消息根本不進(jìn)入消息隊(duì)列。

測(cè)試2那么什么時(shí)候進(jìn)入隊(duì)列呢我來看看這個(gè)例子

沿用上面那個(gè)例子的代碼我將 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 運(yùn)行 等待程序停在斷點(diǎn)處,看Call Stack 如下:


clip_image001
此主題相關(guān)圖片如下:
clip_image005

我們發(fā)現(xiàn)這個(gè) Call Stack 就和剛才那個(gè)PostMessage Call Stack 是一樣的 這個(gè) WM_USER + 100 消息是通過 Run 內(nèi)部的 GetMessage 取出來的 。所以我斷定:

 

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

()       SendMessage 產(chǎn)生的 死鎖問題

Thread 死鎖肯定是發(fā)生在2個(gè)Thread 之間,AB B A,就產(chǎn)生了死鎖。大家看了上面測(cè)試之后一定會(huì)發(fā)現(xiàn),SendMessage 的死鎖和上面的第二個(gè)例子有關(guān)系,也就是 說 通過 Thread B W1 發(fā)送消息的時(shí)候又可能會(huì)產(chǎn)生死鎖。

 

 

那么死鎖 何時(shí)產(chǎn)生呢 ?通過上面的例子我們知道了 如果Thread B W1 SendMessage一個(gè)消息,那么 Thread B 的這個(gè)SendMessage 就要等 Thread A 的隊(duì)列中的 消息執(zhí)行完畢才能夠返回,如果在 Thread B SendMessage 的同時(shí) Thread A 等待 Thread B 中的某一處理完畢才能夠繼續(xù)處理消息的話,那么這個(gè)時(shí)候就發(fā)送了死鎖。

 

我們繼續(xù)以測(cè)試來說明:

測(cè)試3

    首先在 CMainFrame中加入一個(gè) 成員變量: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 當(dāng)中添加如下代碼:

                             m_bThreadExit = FALSE;

          AfxBeginThread(ThreadProc,this);

 

          while(TRUE)

          {

             if(m_bThreadExit)

                break;

             Sleep(55);

}

 

 OK 編譯 F5 運(yùn)行 發(fā)現(xiàn)程序 進(jìn)入無響應(yīng)狀態(tài),好這時(shí)我么讓程序 暫停:

看看 2個(gè)Thread Call Stack 都停在那里了?

Main Thread如下:

 

clip_image001此主題相關(guān)圖片如下:
clip_image006

在看看 另一個(gè)線成:



clip_image001
此主題相關(guān)圖片如下:
clip_image007

這會(huì) 是不是 很明了了

MainThread 停在 循環(huán)內(nèi) 等待 m_bThreadExit True,而 另一個(gè)線成 則等待 MainThread 處理完畢 WM_USER + 100 這個(gè)消息,結(jié)果你等我,我等你,死了。。。。

()       處理辦法

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

2 有些時(shí)候 第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里面實(shí)際上調(diào)用的是::SetWindowText 而::SetWindowText 里面有調(diào)用 SendMessage 發(fā)送一個(gè)消息給CWnd 的窗口 ,因?yàn)椋海?span>SetWindowText 內(nèi)部的我們沒有辦法來修改,那我只能去修改 MainThread 當(dāng)中的 While 循環(huán)了。

 

那如何修改呢? ThreadProc 當(dāng)中 SetWindowText之所以被諸塞,就是因?yàn)?它向 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 閱讀(1071) 評(píng)論(2)  編輯 收藏 引用 所屬分類: 雜項(xiàng)學(xué)習(xí)

FeedBack:
# re: 調(diào)用SendMessage 產(chǎn)生死鎖的問題分析
2009-10-16 20:45 | ahenl
SendMessage不放進(jìn)隊(duì)列中的,msdn寫得很清楚:

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

2. 不同線程時(shí), 待接收線程從隊(duì)列中取消息時(shí)執(zhí)行窗口過程,并沒有說消息放進(jìn)隊(duì)列中,只說明了處理時(shí)機(jī): 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.  回復(fù)  更多評(píng)論
  
# re: 調(diào)用SendMessage 產(chǎn)生死鎖的問題分析
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            在线视频精品| 欧美jizzhd精品欧美喷水 | 欧美一级日韩一级| 亚洲精品国产精品国自产在线| 一区二区三区精品久久久| 激情欧美日韩一区| 国产在线精品二区| 国产免费亚洲高清| 国产亚洲一区在线| 国外精品视频| 亚洲大胆在线| 亚洲国产精品专区久久| 亚洲第一在线视频| 欧美一区二区三区免费在线看 | 欧美日韩mv| 欧美日韩在线播放三区四区| 欧美一区激情| 久久精品亚洲一区| 久久亚洲二区| 欧美黄色免费网站| 欧美日韩亚洲高清| 国产精品视频久久| 国产主播一区| 亚洲欧洲一区二区三区在线观看 | 亚洲人成网站在线观看播放| 亚洲精品视频啊美女在线直播| 国产精品国产三级国产| 欧美1区3d| 欧美三级乱人伦电影| 国产精品手机在线| 一区在线免费| 99精品久久久| 欧美一区二区三区精品电影| 久久琪琪电影院| 91久久精品国产| 亚洲免费视频一区二区| 久久高清国产| 欧美日韩精品综合在线| 国产精品爽黄69| 亚洲高清不卡一区| 亚洲欧美激情一区| 欧美国产精品中文字幕| 亚洲综合999| 你懂的视频一区二区| 亚洲啪啪91| 亚洲欧美日韩在线高清直播| 一本久道久久久| 久久人人爽人人爽爽久久| 欧美区日韩区| 久久aⅴ国产欧美74aaa| 欧美激情 亚洲a∨综合| 国产欧亚日韩视频| 亚洲色在线视频| 牛人盗摄一区二区三区视频| 一区二区免费看| 女人色偷偷aa久久天堂| 国产精品永久免费观看| 亚洲免费久久| 免费亚洲一区二区| 欧美一级在线视频| 国产精品久久久久毛片软件| 亚洲全部视频| 免费黄网站欧美| 午夜日韩电影| 国产精品免费观看在线| 欧美—级在线免费片| 国产伦精品免费视频| 夜夜爽99久久国产综合精品女不卡 | 国产综合久久久久久| 亚洲一级免费视频| 亚洲日韩第九十九页| 快播亚洲色图| 在线观看精品一区| 老司机午夜精品| 欧美在线视频播放| 国产精品制服诱惑| 亚洲欧美在线磁力| 亚洲一区二区欧美| 国产精品毛片在线看| 亚洲尤物视频在线| 亚洲私人影院在线观看| 欧美午夜久久久| 亚洲永久免费av| 亚洲综合视频网| 国内精品伊人久久久久av一坑| 久久精品国产亚洲aⅴ| 性伦欧美刺激片在线观看| 国产手机视频精品| 久久综合中文色婷婷| 久久视频在线视频| 亚洲毛片视频| 免费不卡在线视频| 欧美sm极限捆绑bd| 中文国产成人精品久久一| 99国产精品自拍| 国产精品人人爽人人做我的可爱| 欧美一区二区日韩一区二区| 久久精品国产精品| 亚洲精品欧洲| 亚洲视屏在线播放| 影音先锋日韩有码| 久久精品99无色码中文字幕 | 国产精品免费一区二区三区在线观看 | 久久成人av少妇免费| 精品99一区二区| 亚洲国产欧美一区二区三区同亚洲 | 国内精品久久久久久影视8| 亚洲一区二区免费| 欧美一区二区三区日韩| 欧美激情片在线观看| 精品91在线| 999在线观看精品免费不卡网站| 国产精品久久久久久久久果冻传媒 | 91久久亚洲| 国产九区一区在线| 美女日韩在线中文字幕| 欧美成人一区二区在线| 亚洲在线成人精品| 久久久久久久久久久成人| 9色国产精品| 久久高清福利视频| 亚洲自拍偷拍色片视频| 亚洲综合视频网| 国产欧美二区| 亚洲激情影院| 狠狠色丁香久久综合频道| 日韩一级欧洲| 伊人狠狠色丁香综合尤物| 亚洲精品一区二区在线| 韩国久久久久| 亚洲午夜免费视频| 亚洲精品影视在线观看| 久久成人综合网| 欧美一区二区成人6969| 欧美日韩美女在线| 亚洲国产91| 亚洲激情电影在线| 久久免费黄色| 浪潮色综合久久天堂| 国产一区二区剧情av在线| 亚洲一级电影| 亚洲一区激情| 欧美精品一区二区在线播放| 欧美**人妖| 国产精品一区二区女厕厕| 免费一级欧美片在线观看| 国产自产精品| 亚洲午夜电影| 午夜精品国产精品大乳美女| 欧美日韩一区二区在线| 亚洲精品久久久久久一区二区| 亚洲电影第1页| 久久色在线播放| 蜜桃久久av| 亚洲国产小视频| 久久夜色撩人精品| 欧美88av| 亚洲黄一区二区三区| 欧美成人一区二区三区| 最新国产精品拍自在线播放| 99成人免费视频| 另类激情亚洲| 久久精品一区四区| 国产欧美精品一区二区三区介绍| 欧美激情亚洲另类| 亚洲伦理一区| 国产精品久久久久久久午夜片| 国产精品99久久不卡二区| 午夜亚洲精品| 国产主播精品在线| 免费国产一区二区| 最新国产の精品合集bt伙计| 亚洲国产另类久久久精品极度| 亚洲香蕉伊综合在人在线视看| 久久精品2019中文字幕| 今天的高清视频免费播放成人| 欧美激情中文字幕一区二区| 亚洲欧美国产精品va在线观看| 嫩草影视亚洲| 国内外成人在线| 欧美日韩一区二区三区在线看| 欧美一区国产二区| 99这里只有精品| 欧美国产综合| 久久久久网址| 午夜免费在线观看精品视频| 91久久精品www人人做人人爽| 国产精品免费电影| 欧美日韩日本网| 欧美大片va欧美在线播放| 校园激情久久| 亚洲先锋成人| 一区二区三区.www| 亚洲欧洲精品一区二区三区波多野1战4 | 亚洲欧美日韩精品久久久久 | 久久综合给合久久狠狠狠97色69| 一区二区三区高清在线| 亚洲国产女人aaa毛片在线| 欧美www视频在线观看| 久久亚洲精品伦理|