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

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

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

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

 

 

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

首先我要先簡要的說明一個(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ù)在哪里我們來看看我的測試結(jié)果:

 

測試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è)測試?yán)拥慕Y(jié)果我判定SendMessage Thread A 中向 W1

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

測試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)生了死鎖。大家看了上面測試之后一定會(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ù)以測試來說明:

測試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>
            亚洲精品韩国| 久久九九有精品国产23| 久久国产精品高清| 亚洲制服丝袜在线| 性欧美暴力猛交另类hd| 小辣椒精品导航| 久久嫩草精品久久久精品| 狂野欧美激情性xxxx| 久久综合网络一区二区| 欧美激情一区在线| 99视频在线精品国自产拍免费观看 | 久久男人av资源网站| 蜜桃久久av一区| 欧美午夜片欧美片在线观看| 国产欧美日韩综合精品二区| 亚洲国产精品va在线观看黑人| 日韩一二三区视频| 久久电影一区| 亚洲精品女av网站| 中日韩美女免费视频网站在线观看| 欧美亚洲日本网站| 欧美阿v一级看视频| 国产美女在线精品免费观看| 亚洲国产日韩在线| 欧美一区三区三区高中清蜜桃| 理论片一区二区在线| 亚洲特色特黄| 欧美激情一区二区三区高清视频| 国产视频一区二区三区在线观看| 亚洲人成人一区二区在线观看| 欧美亚洲专区| 一本大道久久a久久精二百| 久久亚洲精品中文字幕冲田杏梨| 国产精品国产精品国产专区不蜜| 在线观看成人网| 久久99在线观看| 一区二区三区四区国产精品| 狼狼综合久久久久综合网| 国产欧美精品va在线观看| 亚洲精选91| 欧美激情精品久久久久久蜜臀| 亚洲欧美中文字幕| 国产精品高潮呻吟久久| 91久久国产综合久久蜜月精品| 久久不射中文字幕| 亚洲一区二区成人| 欧美四级伦理在线| 99综合视频| 亚洲精品视频在线播放| 欧美激情一区二区三区四区| 亚洲成色777777女色窝| 欧美大片va欧美在线播放| 亚洲破处大片| 蜜桃久久av| 亚洲第一久久影院| 免费视频久久| 久久五月天婷婷| …久久精品99久久香蕉国产| 久久婷婷国产麻豆91天堂| 香蕉久久夜色精品国产使用方法 | 中文av一区二区| 欧美日韩综合| 午夜久久影院| 欧美一区二区三区日韩视频| 国产欧美一级| 久久视频一区二区| 久久先锋影音av| 91久久黄色| 亚洲精品美女在线观看| 欧美日韩成人在线播放| 亚洲香蕉成视频在线观看| 一本久久综合亚洲鲁鲁| 国产精品久久久久久久第一福利| 亚洲欧美欧美一区二区三区| 亚洲亚洲精品三区日韩精品在线视频 | 99re6热在线精品视频播放速度| 欧美片第1页综合| 亚洲在线中文字幕| 欧美一区二区三区视频| 影院欧美亚洲| 亚洲激情成人网| 国产精品欧美精品| 美女国产一区| 欧美日韩亚洲激情| 久久久精品午夜少妇| 欧美不卡三区| 欧美主播一区二区三区| 免费h精品视频在线播放| 中文网丁香综合网| 欧美一区日韩一区| 亚洲精品日韩一| 亚洲欧美日韩一区二区在线 | 久久久亚洲欧洲日产国码αv | 欧美日韩一级大片网址| 亚洲欧美视频| 亚洲欧美成人精品| 国产伦精品一区二区三| 欧美黄免费看| 国产日韩欧美在线视频观看| 亚洲第一精品福利| 国产午夜精品理论片a级探花| 久久蜜臀精品av| 久久久蜜桃精品| 奶水喷射视频一区| 午夜精品久久久久久久白皮肤| 久久久久久国产精品mv| 亚洲欧美影院| 欧美国产视频日韩| 久久裸体艺术| 国产精品永久免费视频| 亚洲精品一级| 亚洲第一页在线| 欧美一激情一区二区三区| 野花国产精品入口| 另类激情亚洲| 久久综合九色综合欧美就去吻| 欧美色123| 亚洲国产欧美一区二区三区久久| 国产在线一区二区三区四区| 在线视频精品一区| 在线亚洲欧美视频| 欧美1区免费| 欧美大片在线看免费观看| 国产人妖伪娘一区91| 亚洲视频一二区| 一区二区三区黄色| 欧美另类极品videosbest最新版本| 老牛嫩草一区二区三区日本| 国产女精品视频网站免费 | 久久精品国产亚洲精品| 欧美一区二区三区的| 国产精品s色| 中国女人久久久| 亚洲一区二区三| 国产精品v亚洲精品v日韩精品| 日韩视频精品在线| 亚洲一区二区三区在线| 国产精品高清在线观看| 日韩视频在线观看一区二区| 日韩一级大片| 欧美私人网站| 亚洲伊人观看| 久久九九全国免费精品观看| 国产综合第一页| 老司机午夜精品视频| 亚洲大胆女人| 一本久道久久综合狠狠爱| 欧美日韩另类在线| 亚洲桃花岛网站| 久久久精品动漫| 亚洲黄色毛片| 欧美日韩一区二区欧美激情 | 亚洲一区免费观看| 国产精品国产三级国产专播精品人| 亚洲小说欧美另类婷婷| 久久久久99| 亚洲九九精品| 国产精品性做久久久久久| 久久99伊人| 亚洲精品韩国| 久久精彩视频| 亚洲精品在线免费| 国产精品成人观看视频国产奇米| 亚洲欧美日韩中文在线制服| 麻豆精品一区二区av白丝在线| 亚洲人www| 国产精品欧美日韩久久| 欧美在线视屏| 香蕉久久一区二区不卡无毒影院 | 亚洲国产精品女人久久久| 99热在这里有精品免费| 国产精品丝袜久久久久久app| 欧美在线精品免播放器视频| 亚洲国产天堂网精品网站| 亚洲欧美日韩一区二区在线| 激情五月***国产精品| 欧美日韩综合一区| 久久精品成人欧美大片古装| 亚洲另类在线一区| 久久亚洲国产成人| 亚洲免费伊人电影在线观看av| 精品福利免费观看| 国产精品美女久久久久久久| 六月婷婷久久| 亚洲欧美另类国产| 亚洲三级色网| 欧美a级一区二区| 欧美一区二区视频免费观看| 亚洲毛片在线观看| 伊人久久综合| 国产嫩草影院久久久久| 欧美日韩日日夜夜| 欧美成人精品三级在线观看 | 国产精品久久久久久久久 | 国产精自产拍久久久久久蜜| 免费亚洲一区| 久久九九热re6这里有精品| 亚洲一区二区三区四区视频| 日韩视频在线观看免费| 亚洲狠狠丁香婷婷综合久久久|