MFCで、windows アプリケーションを作っています。
dialogの上に、いくつかの、CListControlのオブジェクトが存在していて、それぞれが、
別の、メッセージを表示するようになっています。
現状は、マルチスレッドを用いずに、メッセージの処理を行っているのですが、それぞれ
のメッセージごとに、スレッドを割り当てて、処理を独立に行いたいと考えています。
メッセージの投げる側は、処理が終わるのを待つために、SendMessageをもちいて、その
ClistControlのオブジェクトのWindow HANDLEへ、メッセージを投げたいです。
そこで、質問なのですが、投げられたメッセージを、新しく作ったスレッドに処理させる
ためには、どのようにすればいいのでしょうか?
環境は、
W2k
VC++6.0
よろしくお願いします。
レスが付いていないようなので、あえて書き込ませて頂きます。
はっきり言って何を質問したいのかが分かりません(^^;。
この質問の仕方じゃなかなかレスつかないと思います。
CListCtrlオブジェクトってダイアログのメンバですよね?
ワーカースレッドからCListCtrlにメッセージ投げたいなら、PostMessageすれば届きま
す。
でも
>投げられたメッセージを、新しく作ったスレッドに処理させるためには、どのようにす
ればいいのでしょうか?
とか書いてありますが、意味不明です。
メインスレッドからワーカースレッドにメッセージ投げるんですか?
CListCtrlってメインスレッドのオブジェクトでしょ?
まぁ、どうしてもメインスレッドからワーカースレッドにメッセージ投げたいなら(そ
んな事する人めったにいないと思いますが、、、)、
たぶん、メインスレッドからPostThreadMessageして、PeekMessageとかで受け取ればで
きると思いますが、やった事ないので分かりません。
では、頑張って下さい。
すみません。ちょっと、スレッドと、メッセージの関係で混乱していて。。
サンプルプログラムを、書きました。
はじめに、CThreadedDlg という Dialogを作ります。OKボタンを押すと、下のメッセー
ジハンドラーが呼ばれます。
その中で、ユーザーインターフェーススレッドが、作られます。このスレッドは、
MessageDlgという、べつの、Dialogを作ります。MessageDlgは、WM_MESSAGEのメッセージ
ハンドラーを持っています。
スレッドが作られた後に、MessageDlgに、1秒おきに10回メッセージを送ります。
期待しているのは、2スレッドが、同時にメッセージを処理することです。つまり
CThreadedDialogDlg::OnOK() が、リターンする前に、その中で送られているMessageDlg
へのメッセージを別のスレッドが処理をすることです。
でも、これは、うまくいかず、OnOkが、リターンする前は、何も起こりません。
質問は、上のように、メッセージを同時に処理をするには、どのようにすればいいのでし
ょうか?よろしくお願いします。
void CThreadedDialogDlg::OnOK()
{
if(m_pThread == NULL)
{
m_pThread = new CUIThread();
m_pThread->m_bAutoDelete = FALSE; // Disable auto deletion
of thread object upon thread termination.
m_pThread->SetParent(this);
// Set the display message.
m_pThread->SetString(This is a threaded dialog box.\n\nThis
message will be cleared in 10 second(s) or when OK button is depressed.);
// Start the interface thread.
m_pThread->CreateThread();
m_nDownCounter = 10;
SetTimer(1, 1000, NULL);
CWnd* pWnd = GetDlgItem(IDOK);
pWnd->EnableWindow(FALSE);
while(m_nDownCounter > 0)
{
m_szMessage.Format(This is a threaded dialog box.\n\nThis
message will be cleared in %d second(s) or when OK button is depressed., --
m_nDownCounter);
::SendMessage(m_pThread->m_Dlg.m_hWnd,WM_MYMESSAGE,(WPARAM)
&m_szMessage,0);
Sleep(1000);
}
}
}
----
void CMessageDialog::OnMyMessage(WPARAM wParam,LPARAM lParam)
{
CString* szString = (CString*)wParam;
m_szMessage = *szString;
UpdateData(FALSE);
}
takeさん、こんにちは。
takeさんのやりたい事は、一つのスレッドで仕組んだSetTimerを
2つのUIスレッドで同時に処理したいという事でよろしいのでしょうか?
takeさんのコードを見る限り、まずスレッド以前の問題で、CThreadedDialogDlg::OnOK
()が終了するまでSetTimerは動作しませんよ(^^;。
後、UIスレッドにメッセージを投げる時に::SendMessageを使うというのはどこに書いて
ありました?
ちゃんと、CWinThread::PostThreadMessageを使って下さい。
CThreadedDialogDlg側は
void CThreadedDialogDlg::OnOK()
{
pThread = (CMessageDialog*) AfxBeginThread(
RUNTIME_CLASS(CMessageDialog),
THREAD_PRIORITY_NORMAL,
NULL,
0,
NULL);
nIDEvent = SetTimer( 1, 1000, NULL );
}
void CThreadedDialogDlg::OnTimer(UINT nIDEvent)
{
pThread->PostThreadMessage( WM_TIMER, 0, 0 );
//なにかの処理
}
とかやって、
CMessageDialog側は、
BEGIN_MESSAGE_MAP(CMessageDialog, CWinThread)
ON_THREAD_MESSAGE( WM_TIMER, OnTimer )
END_MESSAGE_MAP()
void CMessageDialog::OnTimer(WPARAM idEvent, LPARAM dwTime)
{
//なにかの処理
}
とでもして下さい。(以上エラー処理省略)
私も人に何か言えるほどのレベルではありませんが、頑張って下さい。
メインスレッドもサブスレッドもひとつメッセージの処理が終了しないと
次の処理を行えません。
メインスレッドでの処理とユーザインタフェーススレッドはこんな感じに作ります。
メインスレッド
CXXXThread* pXXXThread ;
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_MESSAGE(WM_USER_MSG_TIME, OnMsgTime)
END_MESSAGE_MAP()
BOOL CXXXDlg::CreateXXXThread()
{
CRuntimeClass* pRuntime = RUNTIME_CLASS(CXXXThread);
pXXXThread = (CXXXThread*)AfxBeginThread( pRuntime,
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED,
NULL );
if(pXXXThread ==NULL) {
return FALSE ;
}
pXXXThread->Initial(this) = FALSE ;
pXXXThread->m_bAutoDelete = FALSE ;
pXXXThread->ResumeThread() ;
return TRUE;
}
void CXXXDlg::DestroyXXXThread()
{
if(pXXXThread!=NULL) {
pXXXThread->PostThreadMessage(WM_USER_THREAD_DESTROY, 0, 0) ;
WaitForSingleObject(pXXXThread->m_hThread, INFINITE) ;
delete pXXXThread ;
pXXXThread = NULL ;
}
}
void CXXXDlg::OnOK()
{
if(pXXXThread!=NULL) {
pXXXThread->PostThreadMessage(WM_USER_THREAD_MSG, 0, 0) ;
}
}
LRESULT CXXXDlg::OnMsgTime(WPARAM wParam, LPARAM lParam)
{
return 0 ;
}
ユーザインタフェーススレッド
#include stdafx.h
// CXXXThread
IMPLEMENT_DYNCREATE(CXXXThread, CWinThread)
CXXXThread::CXXXThread()
{
}
CXXXThread::~CXXXThread()
{
}
CXXXThread::Initial(CWnd* pMsg)
{
m_pMsg = pMsg ;
}
BOOL CXXXThread::InitInstance()
{
return TRUE;
}
int CXXXThread::ExitInstance()
{
return CWinThread::ExitInstance();
}
BEGIN_MESSAGE_MAP(CXXXThread, CWinThread)
ON_THREAD_MESSAGE(WM_USER_THREAD_DESTROY, OnDestroy)
ON_THREAD_MESSAGE(WM_USER_THREAD_MSG, OnMsg)
END_MESSAGE_MAP()
void CXXXThread::OnDestroy(WPARAM wParam, LPARAM lParam)
{
::PostQuitMessage(0) ;
}
void CXXXThread::OnMsg(WPARAM wParam, LPARAM lParam)
{
// メッセージ処理
for(int n=0; n<10 ; n++) {
m_pMsg->PostMessage(WM_USER_MSG_TIME, 0, 0) ;
Sleep(1000) ;
}
}
はるさん前回はお世話になりました。
あれ以来「別スレッドにMFCオブジェクトのポインタを渡す」という荒技から足を洗いま
した(笑)。上のコード、私も参考にさせていただきます。