【VC++】簡単なマルチスレッド その1
<機能>
(1)AfxBeginThreadを使用したマルチスレッドサンプルです
(2)マルチスレッドでカウントアップ処理を行います
(3)バックグラウンドプログラムの中断、再開ができます
中断:ResumeThread
再開:SuspendThread
(4)バックグラウンド処理が終了を通知します
(5)ダイアログは終了通知を受け取り終了処理をします
<イメージ>
スレッド開始 ボタン押下によりカウントアップを開始
中断 ボタン押下により中断します(中断→再開に変更)
処理が終了したらユーザ定義メッセージで通知します
<動作検証&開発環境>
Visual Studio Community 2017
<使い方>
1.ダイアログベースでThreadSampleプロジェクトを作成
2.エディットボックスとボタンを配置
IDC_EDIT : ReadOnly=TRUE
3.コントロール変数を追加
IDC_EDIT : m_EdtCount(種類EDIT/カテゴリControl)
IDC_BTNST : m_BtnStart(種類BUTTON)
IDC_BTNSTOP : m_BtnStop(種類BUTTON)
IDOK : m_BtnOk(種類BUTTON)
4.終了通知イベントハンドラ追加
カスタムWindowsメッセージ : WM_MYMSG
メッセージハンドラ名 : OnMyMsg
5.ソースを追加
ThreadSampleDlg.h
class CThreadSampleDlg : public CDialogEx
{
//〜〜省略〜〜
afx_msg void OnBnClickedOk();
CButton m_BtnStart;
CButton m_BtnStop;
CButton m_BtnOk;
afx_msg void OnBnClickedBtnst();
afx_msg void OnBnClickedBtnstop();
CEdit m_EdtCount;
protected:
afx_msg LRESULT OnMyMsg(WPARAM wParam, LPARAM lParam);
};
ThreadSampleDlg.cpp
//ユーザ定義メッセージ
#define WM_MYMSG (WM_USER + 100)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_BTNST, m_BtnStart);
DDX_Control(pDX, IDC_BTNSTOP, m_BtnStop);
DDX_Control(pDX, IDOK, m_BtnOk);
DDX_Control(pDX, IDC_EDIT, m_EdtCount);
}
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDOK, &CThreadSampleDlg::OnBnClickedOk)
ON_BN_CLICKED(IDC_BTNST, &CThreadSampleDlg::OnBnClickedBtnst)
ON_BN_CLICKED(IDC_BTNSTOP, &CThreadSampleDlg::OnBnClickedBtnstop)
ON_MESSAGE(WM_MYMSG, &CThreadSampleDlg::OnMyMsg)
END_MESSAGE_MAP()
// CThreadSampleDlg メッセージ ハンドラー
{
CDialogEx::OnInitDialog();
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
pSysMenu->EnableMenuItem(SC_CLOSE, MF_GRAYED);
}
// Framework は、この設定を自動的に行います。
SetIcon(m_hIcon, TRUE); // 大きいアイコンの設定
SetIcon(m_hIcon, FALSE); // 小さいアイコンの設定
m_BtnStart.EnableWindow(TRUE);
m_BtnStop.EnableWindow(FALSE);
m_BtnOk.EnableWindow(TRUE);
m_BtnStop.SetWindowTextW(L"中 断");
m_EdtCount.SetWindowTextW(L"0");
}
関数名 OnBnClickedOk
機能 閉じる ボタン押下イベント
*************************************************/
void CThreadSampleDlg::OnBnClickedOk()
{
CDialogEx::OnOK();
}
関数名 OnBnClickedBtnst
機能 スレッド開始 ボタン押下イベント
*************************************************/
void CThreadSampleDlg::OnBnClickedBtnst()
{
DWORD dwExitCode;
MSG msg;
m_BtnStart.EnableWindow(FALSE);
m_BtnStop.EnableWindow(TRUE);
m_BtnOk.EnableWindow(FALSE);
count = 0;
//AfxBeginThreadについてはDeveloper Network参照
mythread = AfxBeginThread(CountUpThread, this,0,0,NULL);
}
関数名 OnBnClickedBtnstop
機能 中断 ボタン押下イベント
*************************************************/
void CThreadSampleDlg::OnBnClickedBtnstop()
{
CString cs;
DWORD dwExitCode;
m_BtnStart.EnableWindow(FALSE);
m_BtnStop.EnableWindow(TRUE);
m_BtnOk.EnableWindow(FALSE);
//ボタンのキャプションを取得
m_BtnStop.GetWindowTextW(cs);
if (cs == L"中 断") {
m_BtnStop.SetWindowTextW(L"再 開");
//スレッドを再開
if (GetExitCodeThread(mythread->m_hThread, &dwExitCode)) {
if (dwExitCode == STILL_ACTIVE) {
mythread->SuspendThread();
}
}
}
else {
m_BtnStop.SetWindowTextW(L"中 断");
//スレッドを中断
if (GetExitCodeThread(mythread->m_hThread, &dwExitCode)) {
if (dwExitCode == STILL_ACTIVE) {
mythread->ResumeThread();
}
}
}
}
関数名 CountUpThread
機能 ダイアログの変数をカウントアップして表示
*************************************************/
UINT __cdecl CountUpThread(LPVOID p) {
CThreadSampleDlg* pDlg = (CThreadSampleDlg*)p;
CString cs;
while(1){
//100までカウントアップ
pDlg->count++;
if (pDlg->count > 100) break;
//ダイアログのエディットボックスに表示
cs.Format(L"%d",pDlg->count);
pDlg->m_EdtCount.SetWindowTextW(cs);
Sleep(100);
}
::SendMessage(pDlg->m_hWnd, WM_MYMSG, 0, 0);
return 0;
}
関数名 OnMyMsg
機能 ユーザ定義メッセージのイベントハンドラ
*************************************************/
afx_msg LRESULT CThreadSampleDlg::OnMyMsg(WPARAM wParam, LPARAM lParam)
{
AfxMessageBox(L"スレッドが終了しました", MB_ICONINFORMATION);
//処理終了
m_BtnStart.EnableWindow(TRUE);
m_BtnStop.EnableWindow(FALSE);
m_BtnOk.EnableWindow(TRUE);
return 0;
}
よろしければポチッと押してください