
下のプログラムが終わらなくて困っています。
終わらせる方法を教えてください。
#include <windows.h>
#pragmaargsused
HWNDhWmain;
DWORD WINAPI Th(LPVOID)
{
chars[99];
for(unsigned i=0;i<4294967295;i++)
SetWindowText(hWmain,itoa(i++,s,10));
return 0;
}
LONG WINAPI WinProcedure(HWND hW,UINT wM,UINT wP,LONG lP)
{
staticHANDLEhTh;
DWORDthId;
DWORDExitCode;
switch(wM)
{
case WM_CREATE:
hTh=CreateThread(0,0,Th,0,0,&thId);
return 0;
case WM_DESTROY:
GetExitCodeThread(hTh,&ExitCode);
ExitThread(ExitCode);
if(hTh!=0)CloseHandle(hTh);
PostQuitMessage(0);
return 0;
default:
return(DefWindowProc(hW,wM,wP,lP));
}
}
WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int)
{
WNDCLASSwc;
MSGms;
wc.lpszClassName="Q";
wc.lpfnWndProc=(WNDPROC)WinProcedure;
wc.hInstance=hI;
wc.style=CS_HREDRAW|CS_VREDRAW;
wc.cbClsExtra=0;
wc.cbWndExtra=0;
wc.hIcon=LoadIcon(hI,0);
wc.hCursor=LoadCursor(0,IDC_ARROW);
wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName=0;
RegisterClass(&wc);
hWmain=CreateWindow("Q","",WS_OVERLAPPEDWINDOW,0,0,99,99,0,0,hI,0);
ShowWindow(hWmain,SW_SHOW);
UpdateWindow(hWmain);
while(GetMessage(&ms,0,0,0))
{
TranslateMessage(&ms);
DispatchMessage(&ms);
}
return (ms.wParam);
}
No.1ベストアンサー
- 回答日時:
>case WM_DESTROY:
>GetExitCodeThread(hTh,&ExitCode);
>ExitThread(ExitCode);
>if(hTh!=0)CloseHandle(hTh);
スレッド hTh を強制終了させても問題ないのであれば、
case WM_DESTROY:
if (hTh) {
TerminateThread(hTh, 0);
CloseHandle(hTh);
}
とすれば終了しそうです。
しかし、スレッドの強制終了はあまり好ましくないので、スレッド hTh が自分自身で終了するように作成するべきです。
初期値 FALSE の変数に メインスレッド側で TRUE を書き込むことで終了リクエストとし、スレッド hTh は、その変数を定期的に見に行って、自分自身で ExitThread を呼び出すような方法が最も簡単です。
メインスレッド側では、リクエストを出したあとに、WaitForSingleObject(hTh, ...) などでスレッド hTh の終了を待ちます。タイムアウトなら強制終了させることになるでしょう。
この回答への補足
ありがとうございます。
その方法で動きました。
しかしマイクロソフトサイトのコマンドの説明によると両方とも機能は
「1 つのスレッドを終了させます。」
となっていて
ExitThread
解説
スレッドを終了するには、ExitThread 関数を使うのが好ましい方法です。この関数を呼び出すと(開発者が明示的に呼び出すか、スレッドプロシージャが制御を返す際に自動的に呼び出す)、現在のスレッドのスタックは割り当てを解除され、そのスレッドは終了します。そのスレッドにアタッチしているすべての DLL の各エントリポイント関数は、終了コードを受け取って、そのスレッドが DLL からデタッチされていることを通知されます。
TerminateThread
解説
この関数は、スレッドを終了させます。そして、指定したスレッドには、ユーザーモードのコードを実行する機会と、初期のスタックの割り当てを解除する機会がありません。またこの関数は、終了処理が進行中であることを、そのスレッドにアタッチしている DLL へに通知しません。
TerminateThread 関数は、スレッドを無条件に終了させる危険な関数であり、非常に特別な場合にのみ使うべきです。対象とするスレッドが何を実行しているのか正確に把握していて、指定したスレッドが終了の時点で実行している可能性のあるすべてのコードを制御できる場合にのみ呼び出すべきです。
もし何か情報が有れば教えてください。
確かにスレッドが自分で終了するような構成の方がよいので今後は助言の方針で移行と思います。
メインウィンドウでWaitForSingleObjectを使うとロックしやすいので使わないで単純に以下のようにしたら問題でしょうか?
動作は問題ないのですが、スレッドの終わりを確認せずにウィンドウを終了している点が気になります。
#include <windows.h>
HWNDhWmain;
DWORD WINAPI Th(LPVOID p)
{
chars[99];
for(unsigned i=0;i<unsigned(-1);i++)
{
SetWindowText(hWmain,itoa(i,s,10));
if(*(boolean*)p==true)break;
}
return 0;
}
LONG WINAPI WinProcedure(HWND hW,UINT wM,UINT wP,LONG lP)
{
staticbooleanbEnd;
staticHANDLEhTh;
DWORDID;
switch(wM)
{
case WM_CREATE:
bEnd=false;
hTh=CreateThread(0,0,Th,&bEnd,0,&ID);
return 0;
case WM_DESTROY:
bEnd=true;
if(hTh)CloseHandle(hTh);
PostQuitMessage(0);
return 0;
default:return(DefWindowProc(hW,wM,wP,lP));
}
}
WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int)
{
.............................
No.2
- 回答日時:
>もし何か情報が有れば教えてください。
TerminateThreadで問題があるかどうかは、そのスレッドが何をしているかって事だと思います。
GDIリソースなどをリークさせてしまう事もあるでしょうし、ファイルアクセスや通信がクローズまでいかずに終了させられるのは気持ち悪いですよね。
>メインウィンドウでWaitForSingleObjectを使うとロックしやすいので使わないで単純に以下のようにしたら問題でしょうか?
Th で hWmain を参照していますが、タイミングしだいで DestroyWindow されたウィンドウにアクセスすることになります。
終了までに時間のかかるスレッドがあるならば、WM_CLOSE で「終了中です。しばらくお待ちください」などを表示させて、Th が終了する直前に Th からメッセージをポストさせ、メッセージを受けて DestroyWindow する方法なども考えられます。
>if(*(boolean*)p==true)break;
boolean には volatile を付加した方が間違いがなくていいです。
この回答への補足
ありがとうございます。
以下のようにしました。
#include <windows.h>
HWNDhWmain;
DWORD WINAPI Th(LPVOID p)
{
chars[99];
for(unsigned i=0;i<unsigned(-1);i++)
{
SetWindowText(hWmain,itoa(i,s,10));
if(0<*(int*)p)break;
}
*(int*)p=2;SendMessage(hWmain,WM_CLOSE,0,0);
return 0;
}
LONG WINAPI WinProcedure(HWND hW,UINT wM,UINT wP,LONG lP)
{
staticintiEnd;
staticHANDLEhTh;
DWORDID;
switch(wM)
{
case WM_CREATE:
iEnd=0;
hTh=CreateThread(0,0,Th,&iEnd,0,&ID);
return 0;
case WM_CLOSE:
if(iEnd<2)
iEnd=1;
elseDestroyWindow(hW);
return 0;
case WM_DESTROY:
if(hTh)CloseHandle(hTh);
PostQuitMessage(0);
return 0;
default:return(DefWindowProc(hW,wM,wP,lP));
}
}
*(int*)p=2;
と
SendMessage(hWmain,WM_CLOSE,0,0);
の
間に再びクローズマークをクリックされるとまずそうですね?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) VBA 配列を使ったコードに直していただけますか 4 2023/05/06 15:18
- その他(スマートフォン・携帯電話・VR) Bluetoothイヤホンとスマホの音量を連動させたい 1 2023/03/25 15:55
- 猫 飼い猫の乳腺腫瘍 1 2023/01/26 03:00
- C言語・C++・C# C++のcase文の書き方 4 2023/02/24 20:50
- サッカー・フットサル ワールドカップ決勝最高!!ニワカの自分ですら、メッシが伝説となる最高の試合だということは分かったし、 5 2022/12/19 12:12
- その他(IT・Webサービス) ANDROIDタブレットでZOOMのテストサイトを開いてもテストが始まりません https://ww 1 2023/08/26 16:31
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# カードシャッフルのブログラムを使ってc言語でブラックジャックをしたい 2 2022/04/12 15:13
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
スレッドの監視方法について
-
スレッドの終了はどうやるんで...
-
メインスレッドのPostMessageと...
-
スレッドを効率的に使うとは?
-
.netアプリへのSendMessageでフ...
-
Windows上で、シグナル(SIGTERM...
-
Linuxでスレッド優先度って変え...
-
複数スレッドを動作させるのに...
-
VC++スレッドの正しい終了のさ...
-
スレッドの安全な終了のさせ方
-
Macターミナルで実行中のプログ...
-
C言語で、メモリを解放しないで...
-
SendMessageが失敗するときがある
-
レジスタマップって何ですか?
-
VBSの処理中一旦処理を止めて再...
-
グラフィックLCD SG12...
-
C# シリアル通信でデータ受信...
-
メッセージボックスのボタン名変更
-
分を時間に変換するプログラム
-
ウイルスは必ずタスマネのプロ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
スレッドの監視方法について
-
VC++スレッドの正しい終了のさ...
-
スレッドにて同一メモリの書き...
-
スレッドの終了の仕方
-
VB2005 シリアル通信のClose処理
-
WaitForSingleObjectの使い方に...
-
別スレッドのデータを受信できない
-
同一スレッドで、ロックをかけ...
-
CWnd::OnTimerのスレッドの取得
-
スレッドの安全な終了のさせ方
-
メインダイアログが最背面に表...
-
スレッド一覧の取得
-
Windows上で、シグナル(SIGTERM...
-
C言語で一定時間待機後、再実行
-
C#でスレッド実行中のイベント...
-
複数スレッドを動作させるのに...
-
.netアプリへのSendMessageでフ...
-
DirectX LPDIRECT3DDEVICE9のマ...
-
スレッド内でコントロールやWin...
-
DirectX 11のConsntanBuffer
おすすめ情報