2つのスレッドでCViewの派生クラスのインスタンスを共有したいのですが
どうもうまくいきません。具体的なコーディングは以下の通りです。
void CMyView::OnPostView() //CViewの派生クラス
{
HWND hWnd = GetSafeHwnd();
CMyView* pView = (CMyView*)CWnd::FromHandlePermanent(hWnd);
ASSERT_VALID(pView); //ここでは正しくhWndからCMyViewがつくられる
//別スレッドにhWndを渡す
m_myThread->PostThreadMessage(WM_USER, (WPARAM)hWnd, 0);
}
//CWinThreadの派生クラス(CMyViewのスレッドとは別スレッド)
//WM_USERメッセージで呼ばれる
void CMyThread::OnTestView(WPARAM wParam, LPARAM lParam)
{
CMyView* pView = (CMyView*)CWnd::FromHandlePermanent((HWND)wParam);
//CWnd::FromHandlePermanent呼び出しの途中でデバッガがハングする
ASSERT_VALID(pView);
//CWnd::FromHandlePermanentが成功してもASSERTエラーが発生
}
現象としては、コメントにもあるとおりFromHandlePermanentの呼び出し中に
ハングします。ハングするソースの箇所は一定していません。
PostThreadMessageで渡したhWndとCMyThread::OnTestViewで受け取ったwParamの
値が同じことは確認しています。
ちなみにFromHandlePermanetをFromHandleに変えても同様の現象がおこります。
MSDNに別スレッドにCWndを渡すときはウインドウハンドルを渡して、
受け取った方でウインドウハンドルからCWnd*を得る。というようなことが書いてあったので、
上記のようなコーディングをしてみたのですが、どこが間違っているのでしょう?
ウィンドウハンドルとMFCオブジェクトの対応マップはスレッド固有です。
CMyThreadのスレッドでは渡されたハンドルの対応マップが無いため
CWnd::FromHandlePermanentはNULLを返していると思われます。
この辺は、ウインドウハンドルとMFCのCWndオブジェクトの関係をきちんと勉強された方が
良いともいます。
単純にハンドルからオブジェクト検索するためにこの対応付けを行う必要がありますが、
この対応付けはスレッド単位で行われているので別のスレッドで元のスレッドの対応付けを
参照することが出来ないわけです。
もしCWndクラスを使いたいのであれば、CWndクラスに対してウインドウハンドルをアタッチし
て
使うことになると思います。
ここで気をつける必要があるのは、各スレッドごとにそれぞれ同じウインドウにアタッチされた
CWndが存在することになるので気をつけないと片方が勝手にウインドウの状態を変えてしま
い、
もう片方が破綻すると言った事がおきかねないので気を津片方が良いということ。
アタッチで結びつけた場合は、インスタンスの破棄をする前に必ずデタッチする必要があると
言うことだと思います。
ただ、ウインドウハンドルがあるのであれば、直接Win32APIをコールできるはずなので
それで済ませてしまうというのも一つの方法だと思います。
もとい、誤字脱字の訂正(恥)。
この辺は、ウインドウハンドルとMFCのCWndオブジェクトの関係をきちんと勉強された方が良い
と思います。
もう片方が破綻すると言った事がおきかねないので気を付けた方が良いということ。
いろいろとアドバイスありがとうございます。
確認したいのですが、基本的に異なるスレッド間で
CWnd(およびその派生クラス)の共有はできないと考えていいのですね。
>CWnd(およびその派生クラス)の共有はできないと考えていいのですね。
です。
>>CWnd(およびその派生クラス)の共有はできないと考えていいのですね。
>
>です。
あ、純粋にC++的な使い方(メンバ変数の参照やコマンドハンドラでない単純なメンバ
関数呼び出しとか)なら可ですけど、それ以上のことはできません。
中途半端なので、事実上共有する意味が薄いでしょう。
ウィンドウハンドルを渡しておいて、PostMessage() するとかが一般的な逃げ方かと。
みなさんいろいろと助言ありがとうございます。
マルチスレッドについてはMFCをもっと勉強してから
取り組んでみたいと思います。
ありがとうございました。