執行緒訪問視窗資源的問題

2021-09-30 06:57:00 字數 1428 閱讀 8835

執行緒訪問視窗資源的問題收藏

在開個執行緒

時常為所開的執行緒傳入個視窗引數 (cwnd),,,這裡裡面有個很大的隱患就是當做cwnd::assertvalid()檢查,就會遇到斷言失敗。具體原因在於mfc管理視窗的機制。mfc有個視窗控制代碼和視窗類物件的對映表,就是windows物件(控制代碼)和c++物件的乙個對映,它是在視窗呼叫cwnd::create(),cwnd::createex()時,就新增到對映表裡的。對映表的乙個重要的特徵,它只存於乙個執行緒當中。當你在b執行緒使用a執行緒的視窗物件指標pwnd,b執行緒對此物件指標做assertvalid時,會因為以下幾種原因導致斷言失敗:

1.  chandlemap*   pmap   =   afxmaphwnd();  assert(pmap != null)失敗;該執行緒沒有對映表。原因這個執行緒只是工作執行緒(沒有主視窗),並不是使用者介面執行緒(利用介面執行緒可以在乙個程序的位址空間開啟幾個並行執行的視窗)。在工作執行緒裡呼叫afxgetmainwnd()->m_hwnd出錯,也會發生發生記憶體訪問衝突。(afxgetmainwnd得到的是當前執行緒的主視窗)。

2.assert((p = pmap->lookuppermanent(m_hwnd)) != null ||

(p = pmap->lookuptemporary(m_hwnd)) != null)失敗;從執行緒的控制代碼對映表沒有控制代碼pwnd->m_hwnd所對應  的物件。

3.assert((cwnd*)p == this);控制代碼pwnd->m_hwnd所對應  的物件並不是自身。

進行這幾種斷言的目的:確保c++視窗物件(cwnd)與視窗本身(控制代碼hwnd)間的一致性(一一對應),並不因為只要修改乙個cwnd物件中的m_hwnd值就可改變cwnd與hwnd間的對映關係(合法的修改途徑:對映可以被cwnd成員函式detach,attach所改變),再者可以確保使用視窗的安全性,避免出現訪問違規等狀況,如使用臨時物件就很容易出現這種斷言失敗。

每個介面執行緒都有自身的對映表,tls(執行緒區域性儲存)。對映表有兩類:永久的,臨時的。.普通視窗,如程式主視窗的對映關係在永久對映表中。並不是所有的控制代碼都有個cwnd物件對其進行封裝,所以如果無法在永久對映中找到hwnd對應的cwnd物件,就會建立乙個臨時cwnd物件包裝此hwnd,並將它們記入臨時對映表中.當程式空閒時(onidle()),會刪除所創的臨時視窗物件.此後對該cwnd的引用都將引發上述的斷言出錯(狀況2,3). 也是因這個原因,getdlgitem()等常用函式返回的都是臨時物件,不能在程式中儲存以在以後使用,而應該隨用隨取.注意msdn中的說明:the   returned   pointer   may   be   temporary   and   should   not   be   stored   for   later   use.

下面是斷言原始碼:

void cwnd::assertvalid() const

return pstate->m_pmaphwnd;

}

執行緒訪問視窗資源的問題

在開個執行緒 時常為所開的執行緒傳入個視窗引數 cwnd 這裡裡面有個很大的隱患就是當做cwnd assertvalid 檢查,就會遇到斷言失敗。具體原因在於mfc管理視窗的機制。mfc有個視窗控制代碼和視窗類物件的對映表,就是windows物件 控制代碼 和c 物件的乙個對映,它是在視窗呼叫cwn...

多執行緒訪問視窗控制項時異常問題

net 1.1下允許非同步訪問,不會有異常 在新執行緒中訪問主線程的窗體控制項時會發生錯誤,這個問題大家都知道的。本來以為只要訪問控制項的 寫在窗體的方法中就ok了的,今天試驗了一下卻發生錯誤了。原因是.net 1.1下允許,net 2.0下不允許了。我的 是這樣的 有兩個類,乙個是窗體類,乙個是某...

資源的有序訪問問題

在多執行緒程式中,使用鎖來保證資源的有序訪問,即乙個操作不會導致另乙個正在進行的操作無效。舉個例子,乙個操作正在遍歷乙個list,而另乙個操作卻把這個list clear掉了,導致迭代器失效。然而這個問題並不僅僅是多執行緒才需要考慮的問題。舉個例子,當乙個操作在遍歷list,針對每個元素進行某乙個呼...