|新しいページ|検索|ページ一覧|RSS|@ウィキご利用ガイド | 管理者にお問合せ
|ログイン|

マルチスレッドの制御

※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

ここでは、VC++のMFCを使用したマルチスレッドの制御について記述します。

   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
(省略可) セキュリティ属性。デフォルトでは親スレッドと同じ値。