私はWindows用のアプリケーションを開発しています。私は描画目的でクラスを作成しました。これはいくつかのスレッドによってアクセスされます。このクラスは、mutexロックを使用してスレッドセーフです。子ウィンドウ内でboost :: mutexを使ったC++マルチスレッド
スレッド安全性は問題ではないようですが、WM_SIZEメッセージを処理するときにロックを取得しないようです(他のメッセージを処理するときにロックを取得しますが)理由がわかりません。
クラスには、次のようになります。私は、私の意見では、トラブルを引き起こす可能性がある方法とメンバーを表示するには、それを短縮しました
class DrawChildWindow {
typedef boost::mutex::scoped_lock scoped_lock;
typedef boost::mutex::scoped_try_lock scoped_try_lock;
typedef std::map<HWND, HDC> WindowMap;
public:
DrawChildWindow(HWND hWndParent);
~DrawChildWindow();
// Will move the child window and repaint it
void move(int x, int y, unsigned int cx, unsigned int cy);
// Returns the HDC stored in the WindowMap
HDC beginPaint();
// Displays the edited HDC on the client area of the child window
void endPaint();
private:
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
boost::mutex m_mutexLocal; // for work with member variables
static boost::mutex s_mutexGlobal; // for work with static variables
static WindowMap s_map; // Manages the created child windows
HWND m_hWnd; // Handle of the child window
};
。これは、それぞれの実装です:
DrawChildWindow::DrawChildWindow(HWND hWndParent) {
// I've cut the once-only registration of the window class here
scoped_lock lockG(s_mutexGlobal);
scoped_lock lockL(s_mutexLocal);
m_hWnd = CreateWindow(L"DrawChildWindow", NULL,
WS_CHILDWINDOW | WS_DLGFRAME | WS_VISIBLE,
0, 0, 0, 0,
m_hWndParent, NULL, __DCW_HINST, NULL);
s_map[m_hWnd] = NULL;
}
DrawChildWindow::~DrawChildWindow() {
scoped_lock lockG(s_mutexGlobal);
scoped_lock lockL(s_mutexLocal);
WindowMap::iterator it = s_map.find(m_hWnd);
if(it != s_map.end())
s_map.erase(it);
DestroyWindow();
}
void DrawChildWindow::move(int x, int y, unsigned int cx, unsigned int cy) {
scoped_lock lockL(s_mutexLocal);
MoveWindow(m_hWnd, x, y, cx, cy, TRUE);
}
HDC DrawChildWindow::beginPaint() {
scoped_lock lockG(s_mutexGlobal);
scoped_lock lockL(s_mutexLocal);
WindowMap::iterator it = s_map.find(m_hWnd);
if(it != s_map.end()) {
if(!it->second) {
// I create a compatible DC here
// and fit it to match the client area size
}
// I clear the background of the DC here
return it->second;
}
// This should never happen
return NULL;
}
void DrawChildWindow::endPaint() {
scoped_lock lockG(s_mutexGlobal);
scoped_lock_lockL(m_mutexLocal);
WindowMap::iterator it = s_map.find(m_hWnd);
if(it != s_map.end()) {
if(it->second) {
// I BitBlt the HDC into the client area here
}
}
}
LRESULT CALLBACK DrawChildWindow::WndProc(HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam) {
switch(uiMessage) {
case WM_SIZE:
{ // This is the problematic block
scoped_try_lock lockG(s_mutexGlobal);
// This is never true
if(lockG.try_lock()) {
WindowMap::iterator it = s_map.find(hWnd);
if(it != s_map.end() && it->second) {
DeleteDC(it->second);
it->second = NULL;
}
}
}
return 0;
case WM_PAINT:
{
scoped_lock lockG(s_mutexGlobal);
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd, &ps);
WindowMap::iterator it = s_map.find(hWnd);
if(it != s_map.end() && it->second) {
// I BitBlt it->second to hDC here
}
else {
// Draw a notification that no data is available
}
EndPaint(hWnd, &ps);
}
return 0;
}
return DefWindowProc(hWnd, uiMessage, wParam, lParam);
}
boost::mutex DrawChildWindow::s_mutexGlobal;
DrawChildWindow::WindowMap DrawChildWindow::s_map = WindowMap();
私はWM_SIZE
がCreateWindow()
ながら呼び出されるという事実を認識しています - それはs_mutexGlobal
が実際にロックされている私のコンストラクタに呼び出されます。これが私がscoped_try_lock
として実装した理由です。
親ウィンドウのサイズが変更されたとき、私は子ウィンドウのサイズを調整するためにmove()
を呼び出して、それらが正しく調整されますが、s_map
のHDC
が破壊されることはありません、と私はそこにs_mutexGlobal
をロックできない理由を理解することはできません。