電子書籍の厳選無料作品が豊富!

いつも大変お世話になっております。
VC++初心者です。

現在、下記のサイトでマルチスレッドを勉強していますが、
そのスレッドの呼び出し方が分かりません。
具体的にどのように書けば宜しいのでしょうか。
http://www.takebay.net/~daigo-ao/paddlewiki.pl/t …

mainではないですが、別のクラスから呼び出そうと思い、
以下のように書きましたが、駄目でした。
CHoge aaa;
aaa.RunThread();

お手数ですが、よろしくお願い致します。

A 回答 (2件)

 こんにちは。



 動いてはいますが、10秒間停止した後に終了しています。

 例えばダイアログ上のボタン1で開始、ボタン2で停止するならば、上記URLの

 Sleep(10000);// 10秒待つ
 m_isAlive = false;// スレッドを終了させる

 をコメントアウトして、ダイアログのメンバ変数に
 
 CHoge* m_pHoge;

 を追加、

 ボタン1で、
 m_pHoge = new CHoge();

 ボタン2で
 delete m_pHoge;
 m_pHoge = NULL;

 といった感じでではないでしょうか。

この回答への補足

ご回答、ありがとうござます。
毎回のご教授、感謝しております。

できました!
ありがとうございました。

今回の問題を更に発展させて、
以下の問題についてご指導頂けませんでしょうか。
・ボタン2をを使わずにスレッドの処理が終了したら、
 ボタン2の処理内容(スレッドの削除)を行うには?
・ボタン1を押下のたびに新スレッドを作成するには?
 (CHoge* m_pHogeを配列にしてあげればよいのでしょうか。)
・新規にボタン3を設けて、現在動いているスレッドを強制終了するには?

よろしくお願いします。

補足日時:2009/09/16 10:10
    • good
    • 0

 こんばんは。

補足頂きました。

・ボタン2をを使わずにスレッドの処理が終了したら、ボタン2の処理内容(スレッドの削除)を行うには?
 スレッド側からダイアログクラスに向かって終了通知用のメッセージをポストします。

・ボタン1を押下のたびに新スレッドを作成するには?(CHoge* m_pHogeを配列にしてあげればよいのでしょうか。)
 CArray<CHoge*>を使用した方が楽になると思います。

・新規にボタン3を設けて、現在動いているスレッドを強制終了するには?
 CArray<CHoge*>の全要素を回してスレッドを止める等でしょうか。

 配列の要素を操作中、スレッド間で競合する可能性もあると思うので、クリティカルセクションで排他を行わないとまずそうです。
 取りあえず、ボタン1でスレッドの作成、ボタン2で稼働中の全てのスレッドの停止、1秒程でスレッドの自動停止をしていますが、色々アラもあると思うので参考程度で。

//TestDlg.cppの一番上、ヘッダのインクルードよりは下に置く(此処から)
//終了通知を受ける為のメッセージ
#define WM_ENDTHREAD (WM_USER + 100)

//スレッドクラス
class CHoge
{
public:
enum
{
READY,
RUNNING,
SUCCESS_END,
FORCE_EXIT,
};

private:
static UINT StaticProc(LPVOID pParam)
{
CHoge* pHoge = static_cast<CHoge*>(pParam);
return pHoge->ThreadProc();
}

public:
explicit CHoge(CTestDlg* pParent)
: m_pThread(NULL), m_pParent(pParent), m_iState(READY), m_iCount(0)
{

}

~CHoge()
{

}

bool RunThread()
{
if(m_pThread)
return false;

m_iState = RUNNING;
m_pThread = ::AfxBeginThread(StaticProc, this, 0, 0, CREATE_SUSPENDED);
m_pThread->m_bAutoDelete = TRUE;
m_pThread->ResumeThread();
return true;
}

void SetState(int iState)
{
m_cs.Lock();
m_iState = iState;
m_cs.Unlock();
}

int GetState() const
{
m_cs.Lock();
const int iState = m_iState;
m_cs.Unlock();
return iState;
}

HANDLE GetHandle() const
{
return m_pThread ? m_pThread->m_hThread : NULL;
}

private:
UINT ThreadProc()
{
while(1)
{
::Sleep(200);

switch(this->GetState())
{
case SUCCESS_END:
TRACE("終了\n");
m_pParent->PostMessage(WM_ENDTHREAD, 0, reinterpret_cast<LPARAM>(this));
return 0;

case FORCE_EXIT:
TRACE("強制終了\n");
return 0;

default:
TRACE("実行中\n");
this->Running();
}
}
return 0;
}

void Running()
{
//此処で処理をする

//条件を満たしたらステートを変える
if(++m_iCount > 5)
this->SetState(SUCCESS_END);
}

mutable CCriticalSection m_cs;
CWinThread* m_pThread;
CTestDlg* m_pParent;
int m_iState;
int m_iCount;
};
//(此処まで)

// TestDlg.h : ヘッダー ファイル
//

#pragma once

//追加
#include<afxmt.h>

//追加
class CHoge;

// CTestDlg ダイアログ
class CTestDlg : public CDialog
{
friend CHoge;

// コンストラクション
public:
CTestDlg(CWnd* pParent = NULL);// 標準コンストラクタ

// ダイアログ データ
enum { IDD = IDD_TEST_DIALOG };

protected:
virtual void DoDataExchange(CDataExchange* pDX);// DDX/DDV サポート

// 実装
private:
//追加
CArray<CHoge*> m_pool;

//追加
CCriticalSection m_cs;

//追加
void StartThread();

//追加
void RemoveEndThread(CHoge* pHoge);

//追加
void StopAllThread();

protected:
HICON m_hIcon;

// 生成された、メッセージ割り当て関数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()

public:
//クラスウィザードから追加
afx_msg void OnBnClickedButton1();

//クラスウィザードから追加
afx_msg void OnBnClickedButton2();

//追加
afx_msg LRESULT OnEndThread(WPARAM wParam, LPARAM lParam);
};

// TestDlg.cpp : ソース ファイル
//

BEGIN_MESSAGE_MAP(CTestDlg, CDialog)
//省略
//...
//省略
//追加
ON_MESSAGE(WM_ENDTHREAD,&CTestDlg::OnEndThread)
END_MESSAGE_MAP()

//スレッドを配列に入れてスタート
void CTestDlg::StartThread()
{
m_cs.Lock();

CHoge* pHoge = new CHoge(this);
m_pool.Add(pHoge);
pHoge->RunThread();

m_cs.Unlock();
}

//pHogeを配列から抜き取る
void CTestDlg::RemoveEndThread(CHoge* pHoge)
{
m_cs.Lock();
for(int i = 0; i < m_pool.GetCount(); ++i)
{
if(m_pool[i] != pHoge)
continue;

m_pool.RemoveAt(i);
break;
}
m_cs.Unlock();

::WaitForSingleObject(pHoge->GetHandle(), INFINITE);
delete pHoge;
}

//全てのスレッドを止める
void CTestDlg::StopAllThread()
{
CArray<HANDLE> handles;

m_cs.Lock();

for(int i = 0; i < m_pool.GetCount(); ++i)
{
handles.Add(m_pool[i]->GetHandle());
m_pool[i]->SetState(CHoge::FORCE_EXIT);
}

::WaitForMultipleObjects(handles.GetCount(), handles.GetData(), TRUE, INFINITE);

for(int i = 0; i < m_pool.GetCount(); ++i)
delete m_pool[i];

m_pool.RemoveAll();
m_cs.Unlock();
}

//ボタン1が押された
void CTestDlg::OnBnClickedButton1()
{
// TODO: ここにコントロール通知ハンドラ コードを追加します。
this->StartThread();
}


//ボタン2が押された
void CTestDlg::OnBnClickedButton2()
{
// TODO: ここにコントロール通知ハンドラ コードを追加します。
this->StopAllThread();
}

//スレッドが正常終了した時に来る通知
LRESULT CTestDlg::OnEndThread(WPARAM wParam, LPARAM lParam)
{
this->RemoveEndThread(reinterpret_cast<CHoge*>(lParam));
return 0;
}

この回答への補足

ご回答、ありがとうございます。

長文にわたるご回答ありがとうございます。
今後のコーディングの参考にさせて頂きます。

補足日時:2009/09/20 22:01
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!