「マルチスレッドの制御」の編集履歴(バックアップ)一覧はこちら
「マルチスレッドの制御」(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を使用したマルチスレッドの制御について記述します。
&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 |(省略可) セキュリティ属性。デフォルトでは親スレッドと同じ値。
表示オプション
横に並べて表示:
変化行の前後のみ表示: