ベストアンサー ※ ChatGPTを利用し、要約された質問です(原文:スレッドについて) スレッドについての解説 2007/02/14 13:28 このQ&Aのポイント スレッドについての基本的な説明と、複数のスレッドの作成方法について解説します。スレッドを立ち上げるためのAPIについて説明し、コントロール方法についても触れます。スレッドが終了するかどうかに関わらず、次々とスレッドを立ち上げることができる仕組みについて解説します。 スレッドについて スレッドについて、解らないのですが、 以下の文があると、1つのスレッドが終了するか終了しないかにかかわず、 次々とスレッドを立ち上げるものなんですか? いろいろな、APIでコントロール出来ると思いますが、 基本的には、次々とスレッドを立ち上げるものなんですか? 教えてください。 WM_CREATE: CreateThread(NULL,0,ThreadFunc,&A,0,&WID); CreateThread(NULL,0,ThreadFunc,&A,0,&WID); CreateThread(NULL,0,ThreadFunc,&A,0,&WID); CreateThread(NULL,0,ThreadFunc,&A,0,&WID); CreateThread(NULL,0,ThreadFunc,&A,0,&WID); 質問の原文を閉じる 質問の原文を表示する みんなの回答 (1) 専門家の回答 質問者が選んだベストアンサー ベストアンサー MrBan ベストアンサー率53% (331/615) 2007/02/14 15:09 回答No.1 > 1つのスレッドが終了するか終了しないかにかかわず、 > 次々とスレッドを立ち上げるものなんですか? Yes 少なくとも5個を次々に立ち上げるコードになってます。 > 基本的には、次々とスレッドを立ち上げるものなんですか? 用途次第です。そういう使い方もありますし、違う使い方もあります。 質問者 お礼 2007/02/15 17:11 どうも回答ありがとうございます! >少なくとも5個を次々に立ち上げるコードになってます。 どうもスレッドについてさっぱり解らなかったので、 参考になりました! ありがとうございます! 広告を見て全文表示する ログインすると、全ての回答が全文表示されます。 通報する ありがとう 0 カテゴリ [技術者向] コンピュータープログラミング・開発C・C++・C# 関連するQ&A スレッドについて スレッドについて勉強中なのですが、簡単なスレッド作り、 スレッドの処理が終わってからメインの処理を行わせたくて 以下のようなプログラムを書いてみました。 そこで、WaitForSingleObjectを使ってスレッドが終了するのを 待ちたいのですが、WaitForSingleObjectではまってしまうようで sprintfのメッセージ(スレッドが止まってしまっている)が 表示されません。 WRITE関数の処理が終われば、、WaitForSingleObjectで処理が 戻ってくると考えているのですが…。 スレッドについてと、間違いについて教えてもらえないでしょうか? 宜しくお願いします。 main { if(!stop) { File = CreateFile(...); g_hThead = CreateThread(NULL,0,WRITE,(LPVOID)NULL,0,NULL); g_stop = false; }else { g_stop = true; ::WaitForSingleObject(g_hThead, INFINITE); CloseHandle(File); CloseHandle(hThead ); } } void WRITE() { while(!g_stop) { WriteFile(...); } ...処理を行う sprintf("スレッドを終了します。") } スレッドの終了を知りたい(WindowsAPI) CreateThread()で作成したスレッドの終了を知りたい (具体的には、スレッドが終了するまで待機したい)のですが、 うまくいかず困っています。WindowsAPIに関する本やネットで調べた ところ、WaitForSingleObject()が適用できると考え、 以下のようなプログラムを作成したのですが、 元のスレッドがWaitForSingleObject()のところで 止まると同時に、CreateThread()で作成されたThread_1()も 止まってしまいます。アドバイスいただけますでしょうか。 ----プログラム(該当部分)ここから---- DWORD Thread_1(LPVOID param) { int i; char buff[128]; /* iが99のときのみ終了してよい */ while(g_iFlg == 1) { for(i = 0; i < 100; i++) { Sleep(100); wsprintf(buff, "%d", i); SetDlgItemText((HWND)param, IDC_STATIC_1, buff); } } ExitThread(0); return 0; } BOOL CALLBACK Proc_2(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_INITDIALOG: g_iFlg = 1; g_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread_1, (LPVOID)hDlg, 0, &g_dwThread); return TRUE; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_BUTTON_CANCEL: case IDCANCEL: g_iFlg = 0; WaitForSingleObject(g_hThread, INFINITE); CloseHandle(g_hThread); EndDialog(hDlg, 0); return TRUE; } } return FALSE; } ----プログラム(該当部分)ここまで---- VBで新しいスレッド VBのタイマーコントロールでリストの表示の更新を制御しているのですが、どうも重いので違うスレッドにしてスレッドの優先度を低くしようかと考えました。 しかしCreateThreadでスレッドを作成しようと思っても、必ず強制終了になってしまいます。 おそらくVBが複雑な変数管理構造を採っているからだと思います。 なんでもいいから新しいスレッドを作成する方法があったら教えてください。 ネットワークエンジニアとは?技術職の未来を考える OKWAVE コラム スレッド内でのマルチスレッドの作成[WINDOWSプログラミング] いつもお世話になっております。 現在WINDOWSプログラムでゲームを最中なのですが、スレッド内でスレッドを作成できなくて困っています。 キャラを動かすスレッドで以下の関数を使い、スレッドを作成しようとしたのですが、 CreateThread(NULL, 0, ATK, (LPVOID)&x, 0, &dwID); 以下のようなエラーメッセージが出てしまいます。 'ATK':定義されていない識別子です '関数' : 間接参照のレベルが 'LPTHREAD_START_ROUTINE' と 'int' で異なっています。 'CreateThread' : の型が 3 の仮引数および実引数と異なります。 わかる方いましたらどうがご指導お願いします。 初歩的なミスでしたらすみません。 スレッドの廃棄について ウインドウ上のボタンを押すとあるスレッドがスタートするような プログラムがあるとします。 ボタンのクリックイベントプロシージャ内で 以下のように書いてスレッドをスタートさせることにしたのですが、 Sub MainWnd_CommandButton1_Click() 'スレッドのスタート hThread1=CreateThread(ByVal 0,0,AddressOf(MainOperation),0,0,VarPtr(thread1_ID)) End Sub このままではボタンがクリックされるたびに次々新しくスレッドが 生成されてしまい収拾がつかなくなるのでは?と思います。 基本的に一つのスレッドのみを存在させたいので、 CreateThreadの直前に「CloseHandle(hThread1)」と書こうかとも 思ったのですが、仮にスレッドが存在して無い場合、その場合は 無効なハンドルをクローズすることになりそうで何だか不都合が ありそうです。 スレッドの存在を調べて、あれば安全に廃棄して新しいものをスタート させる、といったことはどのように実装するべきでしょうか? ActiveBasicを使っていますが、教えて頂く際には CやVBでも構いません。 マルチスレッド ウインドウズプログラミングを始めて1ヶ月弱の初心者です。 色々探してみたのですが、結局良く分かりませんでした。 宜しくお願いします。 以下のリンクにおいて、 http://wisdom.sakura.ne.jp/system/winapi/win32/win143.html 1)主スレッドとは、具体的にソースファイルのどこからどこまでのことを言うのでしょうか? そもそもスレッドとは何でしょうか?関数のことでしょうか? また、タスクとは、実行ファイルと考えて良いのでしょうか? 2)副スレッド(ThreadFunc)を作成すると、主スレッド(WinMain?)と副スレッドで並列処理をするとのことですが、CPUは普通一つしかないので、実際は、主スレッド(WinMain?)と副スレッドを常に切り替えながら動作すると思います。が、ここで疑問なのですが、主スレッドと副スレッドの切り替えはいつ誰が行うのでしょうか?また、切り替えタイミング(例えば1ms毎に切り替えたいとか)は自由に設定出来るのでしょうか? 3)"マルチスレッドは親プロセスのメモリ空間を共有します" とあるのですが、これは CreateThread(NULL , 0 , ThreadFunc , (LPVOID)hWnd , 0 , &dwID) の(LPVOID)hWnd を、副スレッド(ThreadFunc)に引数として渡しているから、つまり、主スレッドと副スレッドは、(LPVOID)hWnd だけがメモリを共有する、ということでしょうか? 主スレッドと副スレッドでメモリを共有すると、どんなメリットがあるのでしょうか? 4)マルチスレッドはこういう時に使うとよい、 というような大まかな判断基準があれば教えて下さい。 分かり辛い質問で申し訳有りません。宜しくお願い致します。 CloseHandle() スレッドを、同じハンドルを利用して作る場合、 途中でハンドルの開放が必要か教えてください。 void thread1(); HANDLE handle; //スレッド作成 handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread1, NULL, 0, &dwID); //作ったスレッドの終了を待つ WaitForMultipleObjects(1, handle, TRUE, INFINITE); //スレッドを作った時のハンドルを閉じる。これ必要? CloseHandle(handle); //同じハンドルを利用して別のスレッドであるthread2を作成 handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread2, NULL, 0, &dwID); この、CloseHandle(handle);は必要ですか? Mutexの次の使い方で typedef struct{ HWND hwnd;BOOL th_end;HANDLE hmutex; } DATA, *PDATA; /////////////////////////////////////// static HANDLE hThread1,hThread2; DWORD threadID1,threadID2; static DATA data; static HANDLE hMutex; switch (msg) { case WM_CREATE: //hMutex= //CreateMutex(NULL,FALSE,NULL); data.hwnd = hWnd; data.th_end = FALSE; data.hmutex = hMutex; hThread1=CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)Thread1, (LPVOID)&data, 0,(LPDWORD)&threadID1); hThread2=CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)Thread2, (LPVOID)&data, 0,(LPDWORD)&threadID2); /*x*/hMutex= /*x*/CreateMutex(NULL,FALSE,NULL); break; とするのは正しくて/*x*/の行を削除して//をとり hMutexの位置を前に持ってくるのは間違っているのでしょうか? _beginthread()の使用について 元々スレッドの生成を CreateThread(NULL, 0, ThreadFunc, (LPVOID)¶m, 0, &dwID); としていたのですが、 生成したスレッドがC言語のライブラリを利用する場合、 CreateThread()ではなく_beginthread()を使うとMSDNに記載されていました。 そこでプログラムを_beginthread()に書き換えたのですが、 『error C2440: '関数' : 'DWORD (__stdcall *)(LPVOID)' から 'void (__cdecl *)(void *)' に変換できません。』 『warning C4024: '_beginthread' : の型が 1 の仮引数および実引数と異なります。』 とのエラーが表示されてしまいます。 アドバイスをよろしくお願いします。 #include <windows.h> #include <process.h> #define APP_NAME TEXT("Sample_MainWindow") typedef struct _ThreadParam { HWND owner; POINT point; } ThreadParam; DWORD WINAPI ThreadFunc(LPVOID vdParam) { ・ (省略) ・ } LRESULT CALLBACK WindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { ThreadParam param; switch(uMsg) { case WM_LBUTTONDOWN: param.owner = hWnd; param.point.x = LOWORD(lParam); param.point.y = HIWORD(lParam); _beginthread(ThreadFunc, 0, ¶m); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } WINAPIのスレッドについて教えてください WINAPIのスレッドについて教えてください スレッドを作成して写真をスライドショウー的に表示しようしていますが、 上手くいきません。 typedef struct _dataparam{ HWND hWnd; HDC hSlidDC; int iFileCount; TCHAR szFile[100][MAX_PATH]; HBITMAP hBitmap[100]; }DataParam; という構造体を作成して、各変数に必要な値を代入した後 BIT_SLIDというメッセージが来た場合Threadを作成。 LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp) { static DataParam data={0}; case WM_CREATE: data.hWnd=hWnd; ・ ・ case BIT_SLID: slidCheck=TRUE; CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)SlidThread, (LPVOID)&data,0,&dwThreadId); return 0; Thread関数内でGetClientRectにより下記のように Windowのサイズを測ろうとしましたが rcには正しいWindowのサイズ格納されていません。 DWORD WINAPI SlidThread(LPVOID vdParam) { DataParam *SlidData; RECT rc={0}; SlidData=(DataParam *)vdParam; GetClientRect(SlidData->hWnd,&rc); ・ ・ ・ hWnd以外のiFileCountやszFile[100][MAX_PATH]の値を調べると 問題なく引き渡しているようなのですが、 rcのleft=0 light=459 top=760 bottom=-2142242063となっていました。 けれどThread関数内で InvalidateRect(SlidData->hWnd,NULL,TRUE); 再描画を行います。 ちなみに下記の自作関数では問題なくWindowサイズを取得しております。 int MySetBitmap(HDC hNormalDC,DataParam *data) { GetClientRect(data->hWnd,&rc); ・ ・ ・ 環境はMicrosoft Visual C++ 2008 Express Editionです それと別件なのですが、デバックでローカルに表示される変数と 表示されない変数がありますがその違いを教えていただければ幸いです。 今回SlidDataは表示されません。 ご教授お願いします。 CreateThreadのエラー <プログラム環境> Windows XP VC++6.0 MFC AppWizard(exe) ダイアログベース <質問> 何も実行しないスレッドを作成するようにコーディングしたのですが、 「error C2440: 'type cast' : '' から 'unsigned long (__stdcall *)(void *)' に変換することはできません。」 というエラーが出ました。 これは、何が原因で、解決方法はありますか? <ソース> void CMyDlg::OnButton1() { HANDLE handle; DWORD id; handle = CreateThread(0,0,(LPTHREAD_START_ROUTINE)ThreadFunc,NULL,0,&id); } void CMyDlg::ThreadFunc(void) { } <ヘッダ> void ThreadFunc(void); 宜しければご指摘お願い致します。 グローバル変数が正常に参照できない? Windows2000、VC++6.0 でMFCを使ってダイアログベースのEXEを作っています。 以下のようにグローバル変数をループ処理の終了条件に使ってみたのですが、Release版でビルドしたEXEだと意図した動作となりませんでした。 何か原因について心当たりのある方がいればご教授願います。 ------------------------------------------- BOOL bThreadEndFlag; // 外部変数 ●FuncA()関数でスレッドを作成します。 FuncA() { bThreadEndFlag = FALSE; CreateThread(..., ThreadFunc, ...); Sleep(60000); bThreadEndFlag = TRUE; ◆ ・ ・ } ●スレッドではフラグがFALSEの間ループします。 ThreadFunc() { while(bThreadEndFlag == FALSE ) { X = Y; ★ } } ------------------------------------------- 上記ではスレッド作成後、60秒後にはフラグがTRUEになり、スレッドが終了することを想定した造りになってます。 しかし、実際にはループ処理が終わらず、スレッドが終了しませんでした。 論理的にはちょっと理解できません。。。 いろいろ試して、以下の場合は正常に動作しました。 (1)コードは全く同じままで、Debug版でビルドした場合はOKでした。 (2)★の部分に「Sleep(0)」を追加した場合はRelease版でもOKでした。 <備考> ◆の位置でフラグの値がTRUEになっていることは確認しました。 AIは使う人の年齢や市場にも影響する?人工知能の可能性 OKWAVE コラム Thread.Abortメソッド後の処理について Thread.abortメソッドについて分からないことがあったので,助言が頂けると嬉しいです. Thread.Abort () を発生させると,通常そこでスレッドが終了するということなので,その後のスレッド内の処理はスルーされると思っていたのですが,下記コードですとその後の pictureBox1.Image = null;も実行されている様です. mainでスレッド作成→threadAの停止になると考えていたのですが,delegate内では反映されないのでしょうか? Thread thread_a; //スレッド delegate void Del(); private void main(object sender, EventArgs e) { //スレッドを開始 thread_a = new Thread(new ThreadStart(threadA)); thread_a.Start(); } private void threadA() { new Thread(new ThreadStart(delegate { Invoke((Del)delegate { thread_a.Abort(); //画像を消去する pictureBox1.Image = null; }); })).Start(); } スレッドを2つ作って1秒ごとに2つのスレッドが数値を表示するプログラム スレッドを2つ作って1秒ごとに2つのスレッドが数値を表示するプログラムを作りたいのですがうまくいきません。 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<sys/socket.h> #include<arpa/inet.h> #include<unistd.h> #include<pthread.h> void *threadMain(void *threadArgs); int main(void) { int i = 0; pthread_t threadID; for(i = 0;i < 2;i++){ pthread_create(&threadID,NULL,threadMain,(void *)NULL); } } void *threadMain(void *threadArgs) { int i = 0; while(1){ printf("%d\n",++i); sleep(1); } } 上記プログラムを実行すると1が2回表示されて終了してしまいます。 どこか間違えがあるのでしょうか。。 スレッドの再開 MFCでアプリケーションを開発しています。 メインのプログラムを走らせながら計算処理を行いたくて、本やネット等のサンプルプログラムを見ながら別スレッドを生成してみました。 OnInitDialog()でイベントとスレッドを生成し、スタートボタンのクリック押下をトリガーとして、計算処理(Run())を呼んでいます。 タイマー開始後は一定時間ごと(サンプルでは500msec)にスレッドを再開して計算処理を実行し、計算処理完了後はスレッドを一時停止状態にしたいと思っています。 (アプリケーション起動時にサスペンドモードで起動したスレッドをボタン押下でResumeThread(再開)し、あとはタイマーでイベントシグナルをセットして制御するつもりでした。) ですが、下記のコードで走らせると、初回のみ計算処理が呼び出され、その後はスレッドが再開されません(ThreadProc()がコールされない)。 理解不足から何か考え違いをしているのだと思うのですが、どこをなおすべきかわからず行き詰まっています。 どなたかご指摘頂けたらと思います。よろしくお願い致します。 ※実際に記述したコードの抜粋になりますので計算やリソースの解放処理等は省略しています。 OS:Win10 開発環境:VisualStudio2015 C++ ---------------------------------------------------------------- BOOL CMFCApplication1Dlg::OnInitDialog() { CDialog::OnInitDialog(); 中略 … m_hEvent = CreateEventA(NULL, FALSE, FALSE, "EVENT"); m_hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadProc, (LPVOID)this, CREATE_SUSPENDED, NULL); return TRUE; } void CMFCApplication1Dlg::OnTimer(UINT_PTR nIDEvent) { switch(nIDEvent) { case 1: { BOOL blRet = SetEvent(m_hEvent); } break; default: { } break; } CDialog::OnTimer(nIDEvent); } UINT CMFCApplication1Dlg::ThreadProc(LPVOID pParam) { CMFCApplication1Dlg* pDlg = dynamic_cast<CMFCApplication1Dlg*>(reinterpret_cast<CWnd*>(pParam)); if(pDlg) { pDlg->ThreadProcCall(); } return 0; } // LineProfileスレッド処理呼び出し. void CMFCApplication1Dlg::ThreadProcCall(void) { // イベントオブジェクト取得. HANDLE h = OpenEventA(EVENT_ALL_ACCESS, FALSE, "EVENT"); // シグナル状態になるまで待機. WaitForSingleObject(h, INFINITE); // 非シグナル状態に. ResetEvent(h); // 計算処理呼び出し. Run(); this->SendMessage(WM_USER_COMPLETE_PROC); } void CMFCApplication1Dlg::Run(void) { // 計算処理. } // LineProfileスレッド終了後処理. afx_msg LRESULT CMFCApplication1Dlg::OnCompleteProc(WPARAM wParam, LPARAM lParam) { // スレッド停止. DWORD dwRet = SuspendThread(m_hThread); return 0; } void CMFCApplication1Dlg::OnBnClickedBtnStart() { // スレッド再開. DWORD dwRet = ResumeThread(m_hThread); // 計算処理呼び出し用タイマー設定. m_nUpdatePaintTimer = SetTimer(1, 500, NULL); } スレッドの安全な終了のさせ方 スレッドの安全な終了のさせ方 メインスレッドにてCreateThread命令を使い、あるサブスレッドを作りました。 このサブスレッドは内部でmallocを使い動的に配列領域を確保して その配列領域をforループ等で「かなり時間の掛かる処理」として繰り返し アクセスしています。 ループが終了した時に「free」を実行してmalloc領域を開放しています。 アプリ終了時にメインスレッドからこのサブスレッドを終了させるのに メインウインドウにWM_DESTROYメッセージが送られた時、これまで単に そこで「CloseHandle(hSubThread);」とだけ書いていたのですが、 もしかしたらこれでは場合によっては(サブスレッドがループ処理中だったら) malloc領域が開放されずにリークしてしまうのではないかと思いました。 そこでイベントオブジェクトを使い、サブスレッドがループ処理中の 時には非シグナル状態にして、ループが終了しfreeで領域を開放した後 シグナル状態にするということにして、メインスレッドはそれを WaitForSingleObjectで待つという構造にしました。 ところが「メインスレッドに待ちを作るな」という言葉通り、これでは 上手く行きませんでした。サブスレッドはその時間の掛かる処理の 最中でSendMassage等でメインスレッドの処理を促すような命令を (例えばその処理の進捗状況を表示するなど)を幾つも行っていたので、 もしWaitFor~でメインを待たせると「サブスレッドの処理も進まなくなり 結果両方がロックして動かなくなってしまう」という悲しい状況に 嵌ってしまうのです。 SendMessageを徹底的に無くすということも考えたのですが、 (例えばPostMessageに書き換えるなどもやってみたのですが、これは 全く意図した動作をしてくれない場合もあり)、別の方法では どうしても代替できないケースもあって、全て消すというのは 現実的ではないのかもと。。 このようなサブスレッドを安全に終了させるにはどうしたら良いでしょうか? あるいは単にデストロイ時にCloseHandleとするだけでも良いのでしょうか? C++におけるスレッド制御に関して C++初心者です。 スレッド制御の勉強をしておりますが、 なかなかうまくいきません。 下記のソースのようにスレッド生成をしておりますが、 スレッド用メソッドには、*を付けて使用するしか方法はないのでしょうか? pthread_createに渡す第3パラメータをメソッド名のみにして、呼ばれ元のメソッドの戻り値をvoid* ではなく、void のみで実施したいと思っておりますが、方法がわかりません。 大変申し訳ございませんが、ご教授よろしくお願いいたします。 ############################################################## # pthread_test.cc ############################################################## #include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <unistd.h> /* * スレッドパラメータ格納用 */ typedef struct { char printVal; int interval; } ThreadParamT; // スレッドイニシャル関数 void *ThreadTest(void *arg) { ThreadParamT *thread_test_param =(ThreadParamT*)arg; while(1) { fprintf(stderr,"%c", thread_test_param->printVal); sleep(thread_test_param->interval); } return NULL; } int main(int argc,char *argv[]) { int status; // スレッドのパラメータ pthread_t thread_test; ThreadParamT thread_test_param; thread_test_param.printVal = 'a'; thread_test_param.interval = 1; // スレッドを生成 status=pthread_create(&thread_test, NULL, ThreadTest, &thread_test_param); if(status!=0){ fprintf(stderr,"ERR! OUT!\n"); exit(1); } // 10s間待つ sleep(10); fprintf(stderr, "\n"); return 0; } ############################################################## wait()したスレッドが起こされるタイミング 以下のコードにおいて。 % java ThreadWaitTest 2 の場合はaと表示したまま止まりますが、 % java ThreadWaitTest 1 の場合はスレッドの終了に伴ってwait()が切れ、bまで表示します。 私の望む動作は前者です。 後者の場合、これはつまりスレッドをwaitした際の待機プールがスレッドオブジェクトの場合、そのスレッドの実行が終了すると待機プールにある待機スレッドを自動でnotify()してしまうことを意味していると思うのですが、この解釈はあっていますか? Java のAPIドキュメントに 「別のスレッドが notify メソッドまたは notifyAll メソッドを呼び出してこのオブジェクトのモニター上で待機するスレッドに通知を出すまで待機します」 とあるように、ユーザが明確的にnotifyしないと起こらないと思いこんでいました。 なぜこういう仕様になっているのでしょうか? また、この仕様について詳しく書いてあるサイトやドキュメントなどありませんでしょうか? public class ThreadWaitTest extends Thread { public Object mutex = new Object(); public static void main(String[] args) { try { ThreadWaitTest test = new ThreadWaitTest(); test.start(); System.out.println("a"); switch (new Integer(args[0])) { case 1: synchronized(test) { test.wait(); } break; case 2: synchronized(test.mutex) { test.mutex.wait(); } break; } System.out.println("b"); } catch (InterruptedException ie) { ie.printStackTrace(); } } public void run() { try { Thread.sleep(5000); } catch (InterruptedException ie){ ie.printStackTrace();} } } 別スレッドとイベントの終了手順について C#の質問になります。 メインフォーム上で別スレッドを起動し、別スレッドからのイベントで メインフォーム上のテキストボックスにメッセージを表示しています。 サンプルソースはフォームにボタン2個とテキストボックス1個を貼り 付けたものになり、ボタン1でスレッド起動、ボタン2で停止させてい ます。 正常パターンでボタン1とボタン2を交互に押下すると意図したとおり テキストボックスにメッセージが出力されます。 このプログラムで、ボタン1を押下し別スレッドが起動した状態で、 フォームの×ボタンを押下すると別スレッドの停止処理中にJoin() 呼び出しで永久に止まってしまいます。 止めるべきスレッド中でイベント(OnTraceEvent)を呼び出している のが問題のような気がします。(この処理がなければ正常) このような時の終了手順の王道的なものはありますでしょうか。 public partial class Form1 : Form { ThreadTest _thread = null; public Form1() { InitializeComponent(); } private void button1_Click( object sender, EventArgs e ) { if ( this._thread == null ) { this._thread = new ThreadTest(); this._thread.TraceEvent += new ThreadTest.TraceEventHandler( OnTrace ); this._thread.Open(); } } private void button2_Click( object sender, EventArgs e ) { if ( this._thread != null ) { this._thread.Close(); this._thread.TraceEvent -= new ThreadTest.TraceEventHandler( OnTrace ); this._thread = null; } } private void OnTrace(String message) { if ( this.IsHandleCreated == false ) { return; } MethodInvoker process = (MethodInvoker)delegate() { textBox1.AppendText( message + "\r\n" ); }; if ( this.InvokeRequired ) { this.Invoke( process ); } else { process.Invoke(); } return; } private void Form1_FormClosed( object sender, FormClosedEventArgs e ) { //フォームの×ボタンを押下した時にスレッドを停止しないと //破棄されたコントロールを操作しようとするため下記を追加 if ( this._thread != null ) { this._thread.Close(); this._thread.TraceEvent -= new ThreadTest.TraceEventHandler( OnTrace ); this._thread = null; } } } class ThreadTest { public delegate void TraceEventHandler( String message ); public event TraceEventHandler TraceEvent; protected virtual void OnTraceEvent( String message ) { TraceEventHandler TraceEventTemp = TraceEvent; if ( TraceEventTemp != null ) { TraceEventTemp( message ); } } private Thread _threadLoop = null; private volatile Boolean _threadFlag = false; public void Open() { //スレッド開始 if ( this._threadLoop == null ) { this._threadLoop = new Thread( new ThreadStart( Loop ) ); this._threadLoop.Start(); while ( !this._threadLoop.IsAlive ) ; } } public void Close() { //スレッド停止 if ( this._threadLoop != null ) { this._threadFlag = false; //this._threadLoop.Abort();//ここを有効にすればとりあえず終了する this._threadLoop.Join(); this._threadLoop = null; } } public void Loop() { this._threadFlag = true; while ( this._threadFlag ) { OnTraceEvent( DateTime.Now.ToString( "yyyy/MM/dd hh:mm:ss:fff" ) ); Thread.Sleep( 100 ); } } } スピンコントロールの扱いについて WINDOWS APIでスピンコントロールの使い方が解りません。 スピンコントロールを使うと、どうやらプロシージャに WM_VSCROLL がきて、 LOWORD(wParam) switch文で扱えばいい、と言うことがわかったのですが、 wParamの下位ワードに何がくるのかがよくわかりません。 ご存知の方いらしたら宜しくお願いします。 注目のQ&A 「You」や「I」が入った曲といえば? Part2 結婚について考えていない大学生の彼氏について 関東の方に聞きたいです 大阪万博について 駅の清涼飲料水自販機 不倫の慰謝料の請求について 新型コロナウイルスがもたらした功績について教えて 旧姓を使う理由。 回復メディアの保存方法 好きな人を諦める方法 小諸市(長野県)在住でスキーやスノボをする方の用具 カテゴリ [技術者向] コンピューター プログラミング・開発 Microsoft ASPC・C++・C#CGIJavaJavaScriptPerlPHPVisual BasicHTMLXMLCSSFlashAJAXRubySwiftPythonパフォーマンス・チューニングオープンソース開発SEOスマートフォンアプリ開発その他(プログラミング・開発) カテゴリ一覧を見る OKWAVE コラム 突然のトラブル?プリンター・メール・LINE編 携帯料金を賢く見直す!格安SIMと端末選びのポイントは? 友達って必要?友情って何だろう 大震災時の現実とは?私たちができる備え 「結婚相談所は恥ずかしい」は時代遅れ!負け組の誤解と出会いの掴み方 あなたにピッタリな商品が見つかる! OKWAVE セレクト コスメ化粧品 化粧水・クレンジングなど 健康食品・サプリ コンブチャなど バス用品 入浴剤・アミノ酸シャンプーなど スマホアプリ マッチングアプリなど ヘアケア 白髪染めヘアカラーなど インターネット回線 プロバイダ、光回線など
お礼
どうも回答ありがとうございます! >少なくとも5個を次々に立ち上げるコードになってます。 どうもスレッドについてさっぱり解らなかったので、 参考になりました! ありがとうございます!