「マルチスレッドの制御」の編集履歴(バックアップ)一覧はこちら

マルチスレッドの制御」(2006/01/29 (日) 16:53:33) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

*ここでは、VC++のMFCを使用したマルチスレッドの制御について記述します。 *開発環境: ・WindowsXP Pro SP2 ・VC++ 6.0 *使用する関数: ・AfxBeginThread(); ・ResumeThread(); ・TerminateThread(); ・WaitForSingleObject(); *サンプルコード: Javaのように簡単にスレッドを実装できるラッパークラス。 デザインパターンにCommandを使用。 使い方はCRunnableインターフェースを実装したクラスAを作成し、 インスタンスのポインタをCJThreadのコンストラクタに渡す。 CJThreadのインスタンスのStart()を呼ぶとCRunnableの実装クラスでオーバーライドしたRun()がスレッド上で処理される。 ---- [JThread.h] /* JThread のインターフェース /* スレッドを実行させたいクラスに継承させて、Run() をオーバーライドする */ class CRunnable { public: CRunnable(){;} virtual ~CRunnable(){;} virtual UINT Run() = 0; }; class CJThread : public CRunnable { public: /* コンストラクタ/デストラクタ */ CJThread(CRunnable* pRunnable){ m_pRunnable = pRunnable; m_hThread = NULL; m_iRet = 0; m_fEnd = FALSE; } virtual ~CJThread(){;} /* スレッド起動 */ HANDLE Start(int nPriority = THREAD_PRIORITY_NORMAL); /* スレッドをサスペンド状態で起動 */ HANDLE Suspend(int nPriority = THREAD_PRIORITY_NORMAL); /* サスペンドしたスレッドをスタート */ DWORD Resume(); /* スレッドを中止 */ void Stop(); /* スレッドが終了するまで待つ */ BOOL Wait(); /* 終了コードの取得 */ BOOL GetReturnValue(UINT &iRet); protected: CJThread(){/* 継承に対応 */ m_pRunnable = NULL; m_hThread = NULL; m_iRet = 0; m_fEnd = FALSE; } private: HANDLE ThreadStart(BOOL fSuspend, int nPriority); UINT ThreadProc(); static UINT ThreadEntry(PVOID pParam); CRunnable* m_pRunnable; HANDLE m_hThread; UINT m_iRet; BOOL m_fEnd; }; ---- [JThread.cpp] #include "stdafx.h" #include "JThread.h" #define THREAD_STOP 0 HANDLE CJThread::ThreadStart(BOOL fSuspend, int nPriority) { CWinThread* pThread = NULL; DWORD dwCreateFlags = 0; if(fSuspend){ dwCreateFlags = CREATE_SUSPENDED; } pThread = AfxBeginThread(ThreadEntry, this, nPriority, 0, dwCreateFlags); if (pThread != NULL) { m_hThread = pThread->m_hThread; } return m_hThread; } UINT CJThread::ThreadEntry(PVOID pParam) { return static_cast<CJThread*>(pParam)->ThreadProc(); } UINT CJThread::ThreadProc() { m_iRet = m_pRunnable->Run(); m_fEnd = TRUE; return m_iRet; } HANDLE CJThread::Start(int nPriority) { m_fEnd = FALSE; return ThreadStart(FALSE, nPriority); } HANDLE CJThread::Suspend(int nPriority) { m_fEnd = FALSE; return ThreadStart(TRUE, nPriority); } DWORD CJThread::Resume() { DWORD dwRet = -1; if(m_hThread != NULL){ dwRet = ResumeThread(m_hThread); } return dwRet; } void CJThread::Stop() { if(m_hThread != NULL){ TerminateThread(m_hThread, THREAD_STOP); } m_fEnd = TRUE; } BOOL CJThread::GetReturnValue(UINT &iRet) { if(!m_fEnd){ return FALSE; }else{ iRet = m_iRet; return TRUE; } } BOOL CJThread::Wait() { BOOL bRet = TRUE; DWORD dwRet = 0; if(m_hThread != NULL){ dwRet = WaitForSingleObject(m_hThread, INFINITE); if(dwRet==WAIT_FAILED){ bRet = FALSE; } }else{ bRet = FALSE; } return bRet; } ---- *TIPS: +AfxBeginThread()の引数について CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL ); :戻り値(CWinThread*)|スレッドオブジェクトのポインタ。メンバ変数のhThreadはResumeThread(), TerminateThread(), WaitForSingleObject()の各関数の引数で必要になる。 :pfnThreadProc|制御関数のアドレス。コールバックプロシージャとして定義しておく必要がある。 :pParam|制御関数に渡すパラメータ。void型のポインタなので基本的に何でも指定できる。 :nPriority |(省略可) 優先順位。デフォルトの優先順位は normal 上から順に優先度の高い値が指定される。 ・THREAD_PRIORITY_TIME_CRITICAL ・THREAD_PRIORITY_HIGHEST ・THREAD_PRIORITY_ABOVE_NORMAL ・THREAD_PRIORITY_NORMAL ・THREAD_PRIORITY_BELOW_NORMAL ・THREAD_PRIORITY_LOWEST ・THREAD_PRIORITY_IDLE :nStackSize |(省略可) スレッドのスタック サイズ(Byte単位)。デフォルトの0では、スレッドを作成したプロセスと同じサイズが指定される。 :dwCreateFlags |(省略可) スレッド作成時に一時停止状態にしたい時に CREATE_SUSPENDED を渡す。デフォルトの0では通常の起動を行う。 :lpSecurityAttrs |(省略可) セキュリティ属性。デフォルトでは親スレッドと同じ値。
ここでは、VC++のMFCを使用したマルチスレッドの制御について記述します。 &nbsp;&nbsp;&color(#ffff00){test} **開発環境: ・WindowsXP Pro SP2 ・VC++ 6.0 **使用する関数: ・AfxBeginThread(); ・ResumeThread(); ・TerminateThread(); ・WaitForSingleObject(); **サンプルコード: Javaのように簡単にスレッドを実装できるラッパークラス。 デザインパターンにCommandを使用。 使い方はCRunnableインターフェースを実装したクラスAを作成し、 インスタンスのポインタをCJThreadのコンストラクタに渡す。 CJThreadのインスタンスのStart()を呼ぶとCRunnableの実装クラスでオーバーライドしたRun()がスレッド上で処理される。 ---- *[JThread.h] /* JThread のインターフェース /* スレッドを実行させたいクラスに継承させて、Run() をオーバーライドする */ class CRunnable { public: CRunnable(){;} virtual ~CRunnable(){;} virtual UINT Run() = 0; }; class CJThread : public CRunnable { public: /* コンストラクタ/デストラクタ */ CJThread(CRunnable* pRunnable){ m_pRunnable = pRunnable; m_hThread = NULL; m_iRet = 0; m_fEnd = FALSE; } virtual ~CJThread(){;} /* スレッド起動 */ HANDLE Start(int nPriority = THREAD_PRIORITY_NORMAL); /* スレッドをサスペンド状態で起動 */ HANDLE Suspend(int nPriority = THREAD_PRIORITY_NORMAL); /* サスペンドしたスレッドをスタート */ DWORD Resume(); /* スレッドを中止 */ void Stop(); /* スレッドが終了するまで待つ */ BOOL Wait(); /* 終了コードの取得 */ BOOL GetReturnValue(UINT &iRet); protected: CJThread(){/* 継承に対応 */ m_pRunnable = NULL; m_hThread = NULL; m_iRet = 0; m_fEnd = FALSE; } private: HANDLE ThreadStart(BOOL fSuspend, int nPriority); UINT ThreadProc(); static UINT ThreadEntry(PVOID pParam); CRunnable* m_pRunnable; HANDLE m_hThread; UINT m_iRet; BOOL m_fEnd; }; ---- *[JThread.cpp] #include "stdafx.h" #include "JThread.h" #define THREAD_STOP 0 HANDLE CJThread::ThreadStart(BOOL fSuspend, int nPriority) { CWinThread* pThread = NULL; DWORD dwCreateFlags = 0; if(fSuspend){ dwCreateFlags = CREATE_SUSPENDED; } pThread = AfxBeginThread(ThreadEntry, this, nPriority, 0, dwCreateFlags); if (pThread != NULL) { m_hThread = pThread->m_hThread; } return m_hThread; } UINT CJThread::ThreadEntry(PVOID pParam) { return static_cast<CJThread*>(pParam)->ThreadProc(); } UINT CJThread::ThreadProc() { m_iRet = m_pRunnable->Run(); m_fEnd = TRUE; return m_iRet; } HANDLE CJThread::Start(int nPriority) { m_fEnd = FALSE; return ThreadStart(FALSE, nPriority); } HANDLE CJThread::Suspend(int nPriority) { m_fEnd = FALSE; return ThreadStart(TRUE, nPriority); } DWORD CJThread::Resume() { DWORD dwRet = -1; if(m_hThread != NULL){ dwRet = ResumeThread(m_hThread); } return dwRet; } void CJThread::Stop() { if(m_hThread != NULL){ TerminateThread(m_hThread, THREAD_STOP); } m_fEnd = TRUE; } BOOL CJThread::GetReturnValue(UINT &iRet) { if(!m_fEnd){ return FALSE; }else{ iRet = m_iRet; return TRUE; } } BOOL CJThread::Wait() { BOOL bRet = TRUE; DWORD dwRet = 0; if(m_hThread != NULL){ dwRet = WaitForSingleObject(m_hThread, INFINITE); if(dwRet==WAIT_FAILED){ bRet = FALSE; } }else{ bRet = FALSE; } return bRet; } ---- *''TIPS'': **AfxBeginThread()の引数について CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL ); :戻り値(CWinThread*)|スレッドオブジェクトのポインタ。メンバ変数のhThreadはResumeThread(), TerminateThread(), WaitForSingleObject()の各関数の引数で必要になる。 :pfnThreadProc|制御関数のアドレス。コールバックプロシージャとして定義しておく必要がある。 :pParam|制御関数に渡すパラメータ。void型のポインタなので基本的に何でも指定できる。 :nPriority |(省略可) 優先順位。デフォルトの優先順位は normal 上から順に優先度の高い値が指定される。 ・THREAD_PRIORITY_TIME_CRITICAL ・THREAD_PRIORITY_HIGHEST ・THREAD_PRIORITY_ABOVE_NORMAL ・THREAD_PRIORITY_NORMAL ・THREAD_PRIORITY_BELOW_NORMAL ・THREAD_PRIORITY_LOWEST ・THREAD_PRIORITY_IDLE :nStackSize |(省略可) スレッドのスタック サイズ(Byte単位)。デフォルトの0では、スレッドを作成したプロセスと同じサイズが指定される。 :dwCreateFlags |(省略可) スレッド作成時に一時停止状態にしたい時に CREATE_SUSPENDED を渡す。デフォルトの0では通常の起動を行う。 :lpSecurityAttrs |(省略可) セキュリティ属性。デフォルトでは親スレッドと同じ値。

表示オプション

横に並べて表示:
変化行の前後のみ表示:
目安箱バナー