VisualC++6.0について質問です。
ワーカースレッドからビューを更新するには
どうすればよいのでしょうか。
次のコードを実行するとUpDateAllViewsのところで
「Debug Assertion Failed!」となります。
void CMyApp::OnStartWorkerThread()
{
CMyDoc* pDoc = (CMyDoc *)((CFrameWnd *)AfxGetMainWnd())->GetActiveDocument();
THREADPARMS* ptp = new THREADPARMS;
ptp->pDoc = pDoc;
AfxBeginThread(ThreadFunc, ptp); // ワーカースレッド作成
}
/*--------- ワーカースレッド処理 ---------*/
UINT ThreadFunc(LPVOID pParam)
{
THREADPARMS* ptp = (THREADPARMS *)pParam;
CMyDoc* pDoc = ptp->pDoc;
pDoc->UpdateAllViews(NULL); // 実行時ここでDebug Assertion Failed!
delete ptp;
return 0;
}
私なら
ワーカスレッドにドキュメントへのハンドルを渡しておいて
ワーカスレッドからそこにユーザー定義メッセージを投げて
そのハンドラ関数でUpdateAllViews()します。
試してませんけど(^^;
あまりよく分からないのですが、
ドキュメントと結びついているウィンドウのハンドルを渡して
そこにメッセージを送ればよいのでしょうか?
また、次のように自分でメッセージを定義してみたのですが、
クラスウィザードにメッセージが現れません。
どうすればよいのでしょうか。
#define WM_USER_THREAD_UPDATE_ALLVIEWS WM_USER+0x100
SendMessage(hWnd, WM_USER_THREAD_UPDATE_ALLVIEWS , 0, 0);
よろしくお願いします。
ワーカスレッドからViewに対してユーザー定義メッセージを投げましょうか。
THREADPARMS構造体のメンバに HWND hWndを追加する。(Viewのハンドル用に使う)
AppのInitInstance()あたりで
CMainFrame* pWnd = (CMainFrame*)m_pMainWnd;
C???View* pView = (C???View*)(pWnd->GetActiveView());
ptp->hWnd = pView->GetSafeHwnd();
としておいてスレッドを起動する。
スレッド内からユーザー定義メッセージをSendする。ptpは書かれている取得方法でOK。
::SendMessage(ptp->hWnd, (WM_USER + 100), (WPARAM)0, (LPARAM)0);
ユーザー定義メッセージは手動で実装します。(ClassWizardは使えません)
--- C???View.h ---
// プロトタイプ宣言
afx_msg LRESULT OnRcvData(WPARAM, LPARAM);
--- C???View.cpp ---
// メッセージマップに登録する。
BEGIN_MESSAGE_MAP(C???View, C???View)
//{{AFX_MSG_MAP(C???View)
ON_WM_TIMER()
...
...
//}}AFX_MSG_MAP
ON_MESSAGE(WM_USER + 100, OnRcvData) //この位置にこの行を追加
END_MESSAGE_MAP()
// ハンドラ関数を追加
LRESULT C???View::OnRcvData(WPARAM wParam, LPARAM lParam)
{
C???Doc* pDoc = (C???Doc*)GetDocument();
pDoc->UpdateAllViews();
}
#こんな感じでしょうか?
#エラーが出たら、その都度必要なファイルはインクルードしてください。(^^;
#Appの派生クラスのヘッダーに下のヘッダーが必要かな?
#include MainFrm.h
#include ???Doc.h
#include ???View.h
> THREADPARMS* ptp = new THREADPARMS;
不具合が出るかはわかりませんが、
スレッドに渡すptpをオート変数にすべきではありません。
Appの派生クラスのメンバに持ったほうが安全です。(^^;
Bunさんに教えていただいたとおりに記述することでうまくいきました。
スレッドに渡すTHREADPARMS変数もクラスメンバに持つように変更しました。
解決できてよかったです。
ありがとうございました。