can anyone tell me why this would freeze?
I'm trying to find a way to terminate a thread from outside of it, and allow the main program to do garbage cleanup, like closing any HANDLEs used or freeing any memory allocated. I trigger an event which should cause that loop inside the thread to end, which it seems to, but then it gets stuck on WaitForSingleObject() which should return once that thread is closed for sure shouldn't it?

#include <Windows.h>
DWORD WINAPI TestProc(LPVOID lpParam);
LRESULT CALLBACK MainProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
typedef struct ThreadStuff
{
	HWND hWnd;
	HANDLE run;
} *PThreadStuff;
ThreadStuff input;
HANDLE hThread;
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,  LPSTR lpCmdLine, int nCmdShow)
{ 
	MSG msg;
	WNDCLASSEX cmain;
	HWND hWnd;

	cmain.cbSize        = sizeof(WNDCLASSEX);
	...
	cmain.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

	RegisterClassEx(&cmain);
	
	hWnd = CreateWindow(L"ThreadTest", L"Thread Test", WS_OVERLAPPEDWINDOW, 300, 300, 512, 384, NULL, NULL, hInstance, NULL);

	if(!hWnd) return 0;
	
	input.hWnd = hWnd;
	input.run = CreateEventA(NULL, true, false, "testEvent");

	hThread = CreateThread(NULL, 0, TestProc, &input, NULL, NULL);

	ShowWindow(hWnd, SW_SHOWNORMAL);
	UpdateWindow(hWnd);
	

	while(GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

LRESULT CALLBACK MainProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch(Msg)
    {
		case WM_DESTROY:
			TerminateThread(hThread, 0);
			PostQuitMessage(WM_QUIT);
			break;
		case WM_KEYUP:
			SetEvent(input.run);
			WaitForSingleObject(hThread, INFINITE);
			
			MessageBoxA(hWnd, "thread finished", "done", MB_OK);
			break;
		default:
			return DefWindowProc(hWnd, Msg, wParam, lParam);
		}
    return TRUE;
}
DWORD WINAPI TestProc(LPVOID lpParam)
{
	PThreadStuff input = (PThreadStuff)lpParam;
	while(WaitForSingleObject(input->run, 0) != WAIT_OBJECT_0)
	{
		SetWindowTextA(input->hWnd, "Hello");
		Sleep(500);
		SetWindowTextA(input->hWnd, "Goodbye");
		Sleep(500);
	}
	return 1;
}

This code should only hang if you lift the key while the worker thread is executing this:

while(WaitForSingleObject(input->run, 0) != WAIT_OBJECT_0)
{
	SetWindowTextA(input->hWnd, "Hello");
	Sleep(500);
	SetWindowTextA(input->hWnd, "Goodbye");

but not this:

Sleep(500);
}

The problem is that SetWindowText actually sends WM_SETTEXT (sends, not posts) so it blocks until the main thread handles it. But after setting the event the main thread is stuck waiting on hThread and you get a deadlock.

To avoid that you should post the message instead of sending it (bear in mind that you can't post WM_SETTEXT, so you'll have to define your own message and handle it in the main thread procedure).

Thanks =D
I actually found figured this one out myself, but forgot to close the post =/
sorry about that.

If you can help though, I have another post going here trying to deal with another problem

Edited 6 Years Ago by VBNick: n/a

This question has already been answered. Start a new discussion instead.