Mfc-multithreading

提供:Dev Guides
移動先:案内検索

MFC-マルチスレッド

Microsoft Foundation Class(MFC)ライブラリは、マルチスレッドアプリケーションのサポートを提供します。 スレッドは、プロセス内の実行のパスです。 メモ帳を起動すると、オペレーティングシステムによってプロセスが作成され、そのプロセスのプライマリスレッドの実行が開始されます。 このスレッドが終了すると、プロセスも終了します。

必要に応じて、アプリケーションに追加のスレッドを作成できます。 MFCアプリケーションのすべてのスレッドは、CWinThreadオブジェクトによって表されます。 ほとんどの場合、これらのオブジェクトを明示的に作成する必要はありません。代わりに、フレームワークヘルパー関数AfxBeginThreadを呼び出して、CWinThreadオブジェクトを作成します。

新しいMFCダイアログベースのアプリケーションを作成して、簡単な例を見てみましょう。

ステップ1 *-静的コントロールのキャプションとIDをそれぞれ[スレッドの開始]ボタン*と *IDC_STATIC_TEXT に変更します。

  • ステップ2 *-2つのボタンをドラッグし、これらのボタンのクリックイベントハンドラーを追加します。

スレッド開始ボタン

  • ステップ3 *-静的テキストコントロールのコントロール変数を追加します。
  • ステップ4 *-CMFCMultithreadingDlg.cppファイルの先頭に次の3つのグローバル変数を追加します。
int currValue;
int maxValue;
BOOL stopNow;
  • ステップ5 *-CMFCMultithreadingDlgクラスにWM_TIMERメッセージを追加します。

OnTimer()の実装は次のとおりです

void CMFCMultithreadingDlg::OnTimer(UINT_PTR nIDEvent) {
  //TODO: Add your message handler code here and/or call default
   CString sStatusMsg;
   sStatusMsg.Format(L"Running: %d", currValue);
   m_ctrlStatus.SetWindowText(sStatusMsg);

   CDialogEx::OnTimer(nIDEvent);
}
  • ステップ6 *-CMFCMultithreadingDlgクラスのAfxBeginThreadで使用するサンプル関数を追加します。
UINT MyThreadProc(LPVOID Param) {
   while (!stopNow && (currValue < maxValue)) {
      currValue++;
      Sleep(50);    //would do some work here
   }

   return TRUE;
}
  • ステップ7 *-スレッドを開始する[スレッドの開始]ボタンのイベントハンドラーの実装です。
void CMFCMultithreadingDlg::OnBnClickedButtonStart() {
  //TODO: Add your control notification handler code here
   currValue = 0;
   maxValue = 5000;
   stopNow = 0;
   m_ctrlStatus.SetWindowText(L"Starting...");
   SetTimer(1234, 333, 0);//3 times per second

   AfxBeginThread(MyThreadProc, 0);//<<== START THE THREAD
}
  • ステップ8 *-スレッドを停止する[スレッドの停止]ボタンのイベントハンドラーの実装です。
void CMFCMultithreadingDlg::OnBnClickedButtonStop() {

  //TODO: Add your control notification handler code here
   stopNow = TRUE;
   KillTimer(1234);
   m_ctrlStatus.SetWindowText(L"Stopped");
}
  • ステップ9 *-完全なソースファイルです。
//MFCMultithreadingDlg.cpp : implementation file
//

#include "stdafx.h"
#include "MFCMultithreading.h"
#include "MFCMultithreadingDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

//CMFCMultithreadingDlg dialog

int currValue;
int maxValue;
BOOL stopNow;

CMFCMultithreadingDlg::CMFCMultithreadingDlg(CWnd* pParent/* = NULL*/)
   : CDialogEx(IDD_MFCMULTITHREADING_DIALOG, pParent) {
   m_hIcon = AfxGetApp() -> LoadIcon(IDR_MAINFRAME);
}
void CMFCMultithreadingDlg::DoDataExchange(CDataExchange* pDX) {
   CDialogEx::DoDataExchange(pDX);
   DDX_Control(pDX, IDC_STATIC_TEXT, m_ctrlStatus);
}

BEGIN_MESSAGE_MAP(CMFCMultithreadingDlg, CDialogEx)
   ON_WM_PAINT()
   ON_WM_QUERYDRAGICON()
   ON_BN_CLICKED(IDC_BUTTON_START,
      &CMFCMultithreadingDlg::OnBnClickedButtonStart)
   ON_WM_TIMER()
   ON_BN_CLICKED(IDC_BUTTON_STOP,
      &CMFCMultithreadingDlg::OnBnClickedButtonStop)
END_MESSAGE_MAP()

//CMFCMultithreadingDlg message handlers

BOOL CMFCMultithreadingDlg::OnInitDialog() {
   CDialogEx::OnInitDialog();

  //Set the icon for this dialog. The framework does this automatically
  //when the application's main window is not a dialog
   SetIcon(m_hIcon, TRUE);       //Set big icon
   SetIcon(m_hIcon, FALSE);      //Set small icon

  //TODO: Add extra initialization here

   return TRUE;//return TRUE unless you set the focus to a control
}

//If you add a minimize button to your dialog, you will need the code below
//to draw the icon. For MFC applications using the document/view model,
//this is automatically done for you by the framework.

void CMFCMultithreadingDlg::OnPaint() {
   if (IsIconic()) {
      CPaintDC dc(this);//device context for painting
      SendMessage(WM_ICONERASEBKGND,
         reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

     //Center icon in client rectangle
      int cxIcon = GetSystemMetrics(SM_CXICON);
      int cyIcon = GetSystemMetrics(SM_CYICON);
      CRect rect;
      GetClientRect(&rect);
      int x = (rect.Width() - cxIcon + 1)/2;
      int y = (rect.Height() - cyIcon + 1)/2;

     //Draw the icon
      dc.DrawIcon(x, y, m_hIcon);
   }else {
      CDialogEx::OnPaint();
   }
}
//The system calls this function to obtain the cursor to display while the user drags
//the minimized window.
HCURSOR CMFCMultithreadingDlg::OnQueryDragIcon() {
   return static_cast<HCURSOR>(m_hIcon);
}

UINT/*CThreadDlg::*/MyThreadProc(LPVOID Param)//Sample function for using in
AfxBeginThread {
   while (!stopNow && (currValue < maxValue)) {
      currValue++;
      Sleep(50);//would do some work here
   }
   return TRUE;
}
void CMFCMultithreadingDlg::OnBnClickedButtonStart() {
  //TODO: Add your control notification handler code here
   currValue = 0;
   maxValue = 5000;
   stopNow = 0;
   m_ctrlStatus.SetWindowText(L"Starting...");
   SetTimer(1234, 333, 0);//3 times per second

   AfxBeginThread(MyThreadProc, 0);//<<== START THE THREAD
}

void CMFCMultithreadingDlg::OnTimer(UINT_PTR nIDEvent) {
  //TODO: Add your message handler code here and/or call default
   CString sStatusMsg;
   sStatusMsg.Format(L"Running: %d", currValue);
   m_ctrlStatus.SetWindowText(sStatusMsg);

   CDialogEx::OnTimer(nIDEvent);
}

void CMFCMultithreadingDlg::OnBnClickedButtonStop() {
  //TODO: Add your control notification handler code here
   stopNow = TRUE;
   KillTimer(1234);
   m_ctrlStatus.SetWindowText(L"Stopped");
}
  • ステップ10 *-上記のコードをコンパイルして実行すると、次の出力が表示されます。

マルチスレッド

  • ステップ11 *-[スレッドの開始]ボタンをクリックします。

スレッドの開始

  • ステップ12 *-[スレッドの停止]ボタンをクリックします。 スレッドを停止します。

スレッドの停止