プロが教える店舗&オフィスのセキュリティ対策術

下のプログラムが終わらなくて困っています。
終わらせる方法を教えてください。

#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);
}

A 回答 (2件)

>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 関数は、スレッドを無条件に終了させる危険な関数であり、非常に特別な場合にのみ使うべきです。対象とするスレッドが何を実行しているのか正確に把握していて、指定したスレッドが終了の時点で実行している可能性のあるすべてのコードを制御できる場合にのみ呼び出すべきです。

もし何か情報が有れば教えてください。
確かにスレッドが自分で終了するような構成の方がよいので今後は助言の方針で移行と思います。

補足日時:2003/06/12 07:03
    • good
    • 0
この回答へのお礼

メインウィンドウで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)
{
.............................

お礼日時:2003/06/12 11:44

>もし何か情報が有れば教えてください。



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));
}
}

補足日時:2003/06/12 23:25
    • good
    • 0
この回答へのお礼

*(int*)p=2;

SendMessage(hWmain,WM_CLOSE,0,0);

間に再びクローズマークをクリックされるとまずそうですね?

お礼日時:2003/06/12 23:57

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