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

S.l.e!ep.¢%

像打了激速一樣,以四倍的速度運轉(zhuǎn),開心的工作
簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

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

?

( ) ?????? SendMessage 的工作機制

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

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

?

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

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

?

測試1 我創(chuàng)建了一個無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 運行程序 等到 程序停止在斷點上,我們看看Call Stack 的調(diào)用順序:


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

?

然后 我又將 SendMessage 改成:

PostMessage(WM_USER + 100,0,0);

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


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

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

從這個測試?yán)拥慕Y(jié)果我判定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
此主題相關(guān)圖片如下:
clip_image005

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

?

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

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

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

?

?

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

?

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

測試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 當(dāng)中添加如下代碼:

???????????????????????????? m_bThreadExit = FALSE;

????????? AfxBeginThread(ThreadProc,this);

?

????????? while(TRUE)

????????? {

???????????? if(m_bThreadExit)

??????????????? break;

??? ???????? Sleep(55);

}

?

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

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

Main Thread 如下:

?

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

在看看 另一個線成:



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

這會 是不是 很明了了

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

( ) ?????? 處理辦法

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

?

那如何修改呢? ThreadProc 當(dāng)中 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);

}

終于搞完了

?

Feedback

# re: 調(diào)用SendMessage 產(chǎn)生死鎖的問題分析   回復(fù)  更多評論   

2009-02-08 22:32 by 放屁阿狗
這些應(yīng)該是很基礎(chǔ)的win32系統(tǒng)開發(fā)的常識,不是新穎的東西
看看ice的AMI、AMD

# re: 調(diào)用SendMessage 產(chǎn)生死鎖的問題分析   回復(fù)  更多評論   

2009-02-10 17:18 by hoya
菜鳥感謝大俠
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            av成人激情| 亚洲国产精品久久91精品| 欧美成年人视频网站| 久久久久青草大香线综合精品| 欧美亚洲一区二区三区| 午夜精品99久久免费| 欧美在线免费播放| 免费亚洲电影在线观看| 亚洲人成在线影院| 在线亚洲美日韩| 性刺激综合网| 欧美顶级少妇做爰| 国产精品视频免费观看www| 国外成人性视频| 一本色道久久综合狠狠躁篇的优点| 亚洲欧美在线x视频| 免费欧美视频| 一区二区欧美国产| 久久免费视频观看| 国产精品扒开腿做爽爽爽软件 | 久久9热精品视频| 欧美成人乱码一区二区三区| 亚洲免费av观看| 久久久蜜桃一区二区人| 欧美性猛交视频| 亚洲三级影院| 久久婷婷综合激情| av成人毛片| 欧美黑人多人双交| 激情一区二区| 久久狠狠亚洲综合| 99在线热播精品免费99热| 麻豆国产精品777777在线 | 夜夜嗨av色一区二区不卡| 久久av一区| 99在线精品观看| 欧美电影在线观看| 又紧又大又爽精品一区二区| 亚洲综合视频一区| 亚洲免费av电影| 欧美经典一区二区| 亚洲人在线视频| 欧美成人精品激情在线观看| 性欧美1819sex性高清| 国产精品久久久久久久久久ktv | 欧美亚洲一区三区| 国产精品国产三级国产普通话99 | 亚洲狠狠丁香婷婷综合久久久| 欧美诱惑福利视频| 免费看亚洲片| 欧美91大片| 亚洲国产成人一区| 女主播福利一区| 亚洲第一免费播放区| 亚洲综合色婷婷| 中日韩视频在线观看| 欧美日本国产一区| 夜夜嗨av一区二区三区| 亚洲精品女av网站| 久久综合导航| 亚洲国产裸拍裸体视频在线观看乱了 | 亚洲欧美日韩精品久久亚洲区 | 欧美国产精品中文字幕| 亚洲激情自拍| 国产精品a级| 亚洲一区二区三区免费视频 | 欧美高清自拍一区| 日韩亚洲成人av在线| 日韩视频免费大全中文字幕| 欧美久久九九| 亚洲欧美一区二区原创| 小处雏高清一区二区三区| 一区二区三区在线观看视频| 欧美高清成人| 欧美午夜女人视频在线| 午夜精品福利一区二区蜜股av| 午夜欧美不卡精品aaaaa| 一区在线免费| 欧美大尺度在线| 欧美激情在线观看| 欧美影院成年免费版| 久久久久久一区| 一区二区日韩伦理片| 先锋影音久久| 亚洲经典在线| 午夜一级久久| 日韩午夜黄色| 久久国产主播精品| 在线视频你懂得一区| 欧美一区二区黄色| 一区二区不卡在线视频 午夜欧美不卡在| 亚洲香蕉伊综合在人在线视看| 国外成人在线| 亚洲一级黄色av| 99国产精品视频免费观看| 欧美亚洲免费电影| 日韩一区二区精品| 久久国产精品免费一区| 一本色道久久综合狠狠躁篇的优点| 欧美专区在线播放| 亚洲无亚洲人成网站77777 | 亚洲一线二线三线久久久| 久久野战av| 欧美日韩一区成人| 免费看的黄色欧美网站| 欧美日韩一区二区在线视频 | 亚洲九九精品| 久久精品日韩| 欧美一区二区成人| 欧美日韩久久精品| 欧美国产精品久久| 国产在线拍偷自揄拍精品| aa级大片欧美| 亚洲国产精品视频一区| 欧美一区二区大片| 久久国产精品久久精品国产| 欧美日韩高清在线观看| 欧美成人一区二区三区| 国产亚洲精品7777| 亚洲视频综合| 亚洲影院免费观看| 欧美三级精品| 9i看片成人免费高清| 国产精品99久久久久久久vr| 欧美国产一区二区| 欧美激情精品| 亚洲精品一区在线观看| 老巨人导航500精品| 久久综合九色综合久99| 国产美女扒开尿口久久久| 亚洲一二三级电影| 性欧美大战久久久久久久久| 欧美日韩精品一区二区天天拍小说 | 国产老女人精品毛片久久| 在线天堂一区av电影| 亚洲综合日韩| 国产精品一卡二卡| 午夜日韩电影| 久久久久久久久久久久久女国产乱| 国产精品网站在线播放| 亚洲一区亚洲| 久久综合九色99| 亚洲精品日本| 欧美视频免费| 午夜日韩电影| 欧美国产日韩一区二区在线观看| 亚洲片在线观看| 欧美视频四区| 欧美一区二区三区免费大片| 麻豆久久婷婷| 一本色道久久综合狠狠躁的推荐| 免费视频亚洲| 亚洲精品在线视频| 国产精品久久久亚洲一区| 欧美亚洲三区| 亚洲国产天堂网精品网站| 一本色道久久综合狠狠躁篇怎么玩 | 欧美无砖砖区免费| 国产日韩欧美综合在线| 欧美sm重口味系列视频在线观看| 亚洲高清在线观看| 9色porny自拍视频一区二区| 亚洲欧美第一页| 国产精品老牛| 欧美一区二区在线免费播放| 欧美大秀在线观看| 日韩午夜免费视频| 午夜精品久久久久久久| 狠狠88综合久久久久综合网| 久久免费的精品国产v∧| 一区二区欧美在线观看| 国产精品久久影院| 久久亚洲国产成人| 久久大香伊蕉在人线观看热2| 欧美理论电影在线观看| 国产自产精品| 亚洲一区二区三区影院| 欧美影视一区| 亚洲伦理精品| 亚洲国产精品电影在线观看| 亚洲欧美99| 国产在线精品成人一区二区三区| 亚洲免费网址| 狂野欧美激情性xxxx| 亚洲精品在线观看免费| 国产午夜亚洲精品理论片色戒| 欧美成年人在线观看| 亚洲欧美一区二区三区久久| 亚洲激情在线观看| 久久久国产精品一区二区三区| 亚洲性视频网站| 亚洲高清二区| 韩日成人在线| 国产亚洲欧美色| 国产精品久久久久久久久久ktv | 亚洲图片欧洲图片av| 亚洲国产精品毛片| 国内精品久久久久影院优| 国产精品高清一区二区三区| 欧美日韩国产一区二区三区地区|