This program is example from book and I assume I retyped it correctly, but there is a problem which I don't understand its reason.
Program, regardles main thread, creates four other, and when I run the program on WinXP it practically hangs the system, but it runs. CPU usage is 100% and I cannot (or I must wait a long while) do anything else. I cannot move/resize or quit the program, and finally I must kill program directly from Windows Task Manager.
I do not have to much experience on using threads but I assume that (like the book writes, and for example a much more slower machine like 386 or 486) that for systems like mine (AMD TB 1GHz, 256MB RAM...) it is not too much overhead if program creates four other threads, and that it should run smoothly as much as any other program of that form.
VC of course compiled this program with no error or warning in report. I seems that everything is OK in code. But it is not!
So I'm asking for your help to resolve this problem.
Here's the code (again I apologize for text length but I cannot clip the critical part since I don't see which one is it ):
#include <windows.h>
#include <math.h>
#include <process.h>
typedef struct
{
HWND hwnd;
int cxClient;
int cyClient;
int cyChar;
BOOL bKill;
}
PARAMS, *PPARAMS;
LRESULT APIENTRY WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("Multi2");
HWND hwnd;
MSG msg;
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = szAppName;
if (!RegisterClass(&wc))
{
MessageBox(NULL, TEXT("This Program Requires Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Multitasking Demo using Threads"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
int CheckBottom(HWND hwnd, int cyClient, int cyChar, int iLine)
{
if (iLine * cyChar + cyChar > cyClient)
{
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
iLine = 0;
}
return iLine;
}
void Thread1(PVOID pvoid)
{
HDC hdc;
int iNum = 0, iLine = 0;
PPARAMS pparams;
TCHAR szBuffer[16];
pparams = (PPARAMS) pvoid;
while (!pparams->bKill)
{
if (iNum < 0)
iNum = 0;
iLine = CheckBottom(pparams->hwnd, pparams->cyClient,
pparams->cyChar, iLine);
hdc = GetDC(pparams->hwnd);
TextOut(hdc, 0, iLine * pparams->cyChar, szBuffer,
wsprintf(szBuffer, TEXT("%d"), iNum++));
ReleaseDC(pparams->hwnd, hdc);
iLine++;
}
_endthread();
}
LRESULT APIENTRY WndProc1(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static PARAMS params;
switch (message)
{
case WM_CREATE:
params.hwnd = hwnd;
params.cyChar = HIWORD(GetDialogBaseUnits());
_beginthread(Thread1, 0, ¶ms);
return 0;
case WM_SIZE:
params.cyClient = HIWORD(lParam);
return 0;
case WM_DESTROY:
params.bKill = TRUE;
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
void Thread2(PVOID pvoid)
{
HDC hdc;
int iNum = 1, iLine = 0, i, iSqrt;
PPARAMS pparams;
TCHAR szBuffer[16];
pparams = (PPARAMS) pvoid;
while (!pparams->bKill)
{
do
{
if (++iNum < 0)
iNum = 0;
iSqrt = (int) sqrt(iNum);
for (i = 2; i <= iSqrt; i++)
if (iNum % i == 0)
break;
}
while (i <= iSqrt);
iLine = CheckBottom(pparams->hwnd, pparams->cyClient,
pparams->cyChar, iLine);
hdc = GetDC(pparams->hwnd);
TextOut(hdc, 0, iLine * pparams->cyChar, szBuffer,
wsprintf(szBuffer, TEXT("%d"), iNum));
ReleaseDC(pparams->hwnd, hdc);
iLine++;
}
_endthread();
}
LRESULT APIENTRY WndProc2(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static PARAMS params;
switch (message)
{
case WM_CREATE:
params.hwnd = hwnd;
params.cyChar = HIWORD(GetDialogBaseUnits());
_beginthread(Thread2, 0, ¶ms);
return 0;
case WM_SIZE:
params.cyClient = HIWORD(lParam);
return 0;
case WM_DESTROY:
params.bKill = TRUE;
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
void Thread3(PVOID pvoid)
{
HDC hdc;
int iNum = 0, iNext = 1, iLine = 0, iTemp;
PPARAMS pparams;
TCHAR szBuffer[16];
pparams = (PPARAMS) pvoid;
while (!pparams->bKill)
{
if (iNum < 0)
{
iNum = 0;
iNext = 1;
}
iLine = CheckBottom(pparams->hwnd, pparams->cyClient,
pparams->cyChar, iLine);
hdc = GetDC(pparams->hwnd);
TextOut(hdc, 0, iLine * pparams->cyChar, szBuffer,
wsprintf(szBuffer, TEXT("%d"), iNum));
ReleaseDC(pparams->hwnd, hdc);
iTemp = iNum;
iNum = iNext;
iNext += iTemp;
iLine++;
}
_endthread();
}
LRESULT APIENTRY WndProc3(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static PARAMS params;
switch (message)
{
case WM_CREATE:
params.hwnd = hwnd;
params.cyChar = HIWORD(GetDialogBaseUnits());
_beginthread(Thread3, 0, ¶ms);
return 0;
case WM_SIZE:
params.cyClient = HIWORD(lParam);
return 0;
case WM_DESTROY:
params.bKill = TRUE;
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
void Thread4(PVOID pvoid)
{
HDC hdc;
int iDiameter;
PPARAMS pparams;
pparams = (PPARAMS) pvoid;
while (!pparams->bKill)
{
InvalidateRect(pparams->hwnd, NULL, TRUE);
UpdateWindow(pparams->hwnd);
iDiameter = rand() % (max (1,
min(pparams->cxClient, pparams->cyClient)));
hdc = GetDC(pparams->hwnd);
Ellipse(hdc, (pparams->cxClient - iDiameter) / 2,
(pparams->cyClient - iDiameter) / 2,
(pparams->cxClient + iDiameter) / 2,
(pparams->cyClient + iDiameter) / 2);
ReleaseDC(pparams->hwnd, hdc);
}
_endthread();
}
LRESULT APIENTRY WndProc4(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static PARAMS params;
switch (message)
{
case WM_CREATE:
params.hwnd = hwnd;
params.cyChar = HIWORD(GetDialogBaseUnits());
_beginthread(Thread4, 0, ¶ms);
return 0;
case WM_SIZE:
params.cxClient = LOWORD(lParam);
params.cyClient = HIWORD(lParam);
return 0;
case WM_DESTROY:
params.bKill = TRUE;
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
LRESULT APIENTRY WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hwndChild[4];
static TCHAR* szChildClass[] = { TEXT("Child1"), TEXT("Child2"),
TEXT("Child3"), TEXT("Child4") };
static WNDPROC ChildProc[] = { WndProc1, WndProc2, WndProc3, WndProc4 };
HINSTANCE hInstance;
int i, cxClient, cyClient;
WNDCLASS wc;
switch (message)
{
case WM_CREATE:
hInstance = (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
for (i = 0; i < 4; i++)
{
wc.lpfnWndProc = ChildProc[i];
wc.lpszClassName = szChildClass[i];
RegisterClass(&wc);
hwndChild[i] = CreateWindow(szChildClass[i], NULL,
WS_CHILDWINDOW | WS_BORDER | WS_VISIBLE,
0, 0, 0, 0,
hwnd, (HMENU) i, hInstance, NULL);
}
return 0;
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
for (i = 0; i < 4; i++)
MoveWindow(hwndChild[i], (i % 2) * cxClient / 2,
(i > 1) * cyClient / 2,
cxClient / 2, cyClient / 2, TRUE);
return 0;
case WM_CHAR:
if (wParam == '\x1B')
DestroyWindow(hwnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
Thanks.
|