環境はWinXPでVisual Studio 2005を使用しています。
C言語で関数をマルチスレッド化するにはこんな感じでOKでした。
// マルチスレッド関数
void Thread( void * )
{
}
void MainFunc()
{
(HANDLE)_beginthread( Thread, 0, NULL );
}
こんな風にスレッド関数をC++のメソッドに変えてうまくいくかと思い
class Test_c {
public:
void Thread( void * );
} ;
// マルチスレッド関数
void Test_c::Thread( void * )
{
}
void MainFunc()
{
Test_c t t;
(HANDLE)_beginthread( t.Thread, 0, NULL );
}
とするとエラーが出てきてしまい、コンパイルが通りませんでした。
C++のメンバ関数をマルチスレッド関数としたい場合はどの様に書けばよいのでしょうか・・?
No.2ベストアンサー
- 回答日時:
こんにちは。
メンバ関数からスタティックメンバ関数のアドレスとthisポインタを渡してスレッドを起動するのが手っ取り早いです。
スレッドに飛び込んだら、其のままパラメータをTest_c*にキャストして、メンバ関数側へ迂回出来ます。
その他、クリティカルセクション等は、外回りで必要に応じてするか、メンバ関数内でするか等、色々有るのですが・・・。
アラも有りますが、取り敢えずは参考程度に。
#include<windows.h>
#include<mmsystem.h>
#include<process.h>
#include<stdio.h>
#pragma comment(lib, "winmm.lib")
//クリティカルセクション
class CCS
{
CRITICAL_SECTION cs;
public:
CCS(){::InitializeCriticalSection(&this->cs);}
~CCS(){::DeleteCriticalSection(&this->cs);}
CRITICAL_SECTION* get() const { return (CRITICAL_SECTION*)&this->cs; }
};
//排他クラス
class CLock
{
const CCS& rccs;
public:
CLock(const CCS& r) : rccs(r){::EnterCriticalSection(rccs.get());}
~CLock(){::LeaveCriticalSection(rccs.get());}
};
//テストクラス
class Test_c
{
enum { ThreadCount = 2 };
HANDLEarrhThread[ThreadCount];
CCSccs;
intvalue;
//マルチスレッド関数(計算)メンバ関数へ転送
static void ThreadCalc(void* p)
{
Test_c* pTest = (Test_c*)p;
pTest->calc();
}
//マルチスレッド関数(表示)メンバ関数へ転送
static void ThreadPrint(void* p)
{
Test_c* pTest = (Test_c*)p;
pTest->print();
}
//メンバ関数(計算)
void calc()
{
::printf("%s\n", "計算開始");
const DWORD dwStartTime = ::timeGetTime();
//1秒間計算する
while(::timeGetTime() - dwStartTime <= 1000)
{
CLock lock(this->ccs);
++this->value;
::Sleep(16);
}
::printf("%s\n", "計算終了");
::_endthread();
}
//メンバ関数(表示)
void print()
{
::printf("%s\n", "表示開始");
const DWORD dwStartTime = ::timeGetTime();
//1.5秒間表示する
while(::timeGetTime() - dwStartTime <= 1500)
{
CLock lock(this->ccs);
::printf("%d\n", this->value);
::Sleep(16);
}
::printf("%s\n", "表示終了");
::_endthread();
}
public:
//全てがシグナルになるまで待つ
static void Wait(Test_c& t)
{
while(1)
{
const DWORD dwResult = ::WaitForMultipleObjects(ThreadCount, t.arrhThread, TRUE, INFINITE);
if(dwResult >= WAIT_OBJECT_0 && dwResult <= WAIT_OBJECT_0 + ThreadCount - 1)
break;
}
}
Test_c() : ccs(), value(0)
{
for(int i = 0; i < ThreadCount; ++i)
arrhThread[i] = NULL;
}
void start()
{
this->arrhThread[0] = (HANDLE)::_beginthread(&Test_c::ThreadPrint, 0, this);
this->arrhThread[1] = (HANDLE)::_beginthread(&Test_c::ThreadCalc, 0, this);
}
void close()
{
for(int i = 0; i < ThreadCount; ++i)
{
::CloseHandle(arrhThread[i]);
arrhThread[i] = NULL;
}
}
};
//お試し
int main()
{
TIMECAPS tc = {0};
::timeGetDevCaps(&tc, sizeof(tc));
::timeBeginPeriod(tc.wPeriodMin);
Test_c test;
test.start();
Test_c::Wait(test);
::timeEndPeriod(tc.wPeriodMin);
return 0;
}
beginthreadってthisポインタが渡せたんですね!!
MSDNでarg_listってなんのこっちゃと思ってたら・・
本当にありがとうございました!
No.3
- 回答日時:
いろいろやり方がありますが、最も自由度が高く、
一般的なのはスレッド関数にthisを渡す方法ですね。
class FOO{
void TH_Start(){
::AfxBeginThread( ThFunc, this,
THREAD_PRIORITY_NORMAL, 0, 0, NULL);
}
void TH_CallBack(){
// ここが実際のスレッドのメインとなります。
}
}
スレッド関数は渡されたクラスオブジェクトの
クラスコールバックを呼ぶたけです。何もしません。
UINT ThreadFunc( PVOID p_obj){// thisが渡される
FOO *p_foo = ( FOO *)p_obj;
p_foo->TH_CallBack();// クラスコールバックを呼ぶ
return 0;
}
この方法では、あまり細かいコードを書かなくて済みますし
初心者にも直感的にわかりやすい点がお勧めです。
MFCには標準でthisを渡せる関数があるんですね~。
ちょっと私の環境ではMFCの導入が厳しいので
次回なにか作るときにぜひ利用してみようと思います。
ありがとうございました!
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/12】 急に朝起こしてきた母親に言われた一言とは?
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・好きな「お肉」は?
- ・あなたは何にトキメキますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・チョコミントアイス
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・あなたの習慣について教えてください!!
- ・ハマっている「お菓子」を教えて!
- ・高校三年生の合唱祭で何を歌いましたか?
- ・【大喜利】【投稿~11/1】 存在しそうで存在しないモノマネ芸人の名前を教えてください
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・家の中でのこだわりスペースはどこですか?
- ・つい集めてしまうものはなんですか?
- ・自分のセンスや笑いの好みに影響を受けた作品を教えて
- ・【お題】引っかけ問題(締め切り10月27日(日)23時)
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・ちょっと先の未来クイズ第4問
- ・【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
【gcc・cygwin】multiple defin...
-
C++にてtemplateで受け取った任...
-
静的でないメンバ関数の呼び出...
-
C言語 ① 5秒間 1秒間隔で点滅を...
-
C# Controls.Addで動的に配置し...
-
const_castのつかいどころを教...
-
typedef unsigned int UINT;が...
-
関数ポインタについて
-
pictureboxの画像を削除するには?
-
void*型の配列について
-
(void)0 はどんな意味ですか
-
C++でオーバーロードに関するバ...
-
既定のコンストラクタがありま...
-
const int i ? int const i ?
-
TimerProc コールバック関数を...
-
int main()、void main()、void...
-
H8マイコンのシリアル通信につ...
-
Enterキーを押されたら次の処理...
-
信頼区間の1.96や1.65ってどこ...
-
C言語での引数の省略方法
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
【gcc・cygwin】multiple defin...
-
静的でないメンバ関数の呼び出...
-
C++にてtemplateで受け取った任...
-
戻り値を返す関数の前に(void)...
-
多重定義が起きている?--lnk20...
-
既定のコンストラクタがありま...
-
C# Controls.Addで動的に配置し...
-
(void)0 はどんな意味ですか
-
int main()、void main()、void...
-
const_castのつかいどころを教...
-
C# KeyDownイベントでショート...
-
VC++でGetKeyboardStateがうま...
-
void*型の配列について
-
C#でラジオボタンを設定に記録...
-
Notepad++の関数リスト表示の変...
-
ArduinoでMouse関数を使用して...
-
_beginthreadにて発生するコン...
-
コールバックって・・・
-
ウインドウの移動禁止
-
構造体を宣言と共に初期化する方法
おすすめ情報