Click to See Complete Forum and Search --> : This is Strange....


msanford
March 26th, 2003, 01:15 AM
Hello again all. I finally have everything working almost mostly thanks to you guys but I have run into a problem and I am stumped. Basically what I am trying to do is load and display a progress box from a dll file, and then return to loop on a function while updating the function. The problem that I have is in order to make sure that the ProgressBox is displayed I loop waiting for the HWND. In code this is what I am doing:

void ShowProgressDialog(FunctionParams* f)
{
fparams=f;
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CreatePrgWindow, (LPVOID)fparams, 0, &dwThreadId);
while (fparams->hwnd==0) ;
}

It goes into a infinite loop at the end and never comes out. (I do set the fparams->hwnd in the CreatePrgWindow). However like a good little programmer when I was testing this I had:

void ShowProgressDialog(FunctionParams* f)
{
fparams=f;
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CreatePrgWindow, (LPVOID)fparams, 0, &dwThreadId);
while (fparams->hwnd==0)
cout << "waiting..." << endl;
}

and this worked fine I got maybe about 10 waitings and the code continues. Any ideas why this is and how I can fix this? Is this possibly a optimization thing and without the cout the compiler thinks that the loop does nothing? I have tried several different combos such as:

while(fparams->hwnd==0)
if (f->hwnd!=0) break;

and

for (int i=0; fparams->hwnd==0; i++)

both just lock into the loop. I am truly lost here and would appreciate any help.

Kheun
March 26th, 2003, 03:07 AM
If I am not wrong, I also think that it is due to the compiler optimization. One way to avoid this, is to declare your variable volatile.

Also, rather than using a empty while loop, I would Sleep() inside the loop so as to prevent eating up all the CPU time.

while (fparams->hwnd==0)
Sleep(100);

teejbee
March 26th, 2003, 09:08 AM
I seriously doubt what the compiler's optimization has to do something here. And moreover using sleep() is not a good idea for synchronizing multiple threads.

Matthew, I assume your FunctionParams is a structure containing hwnd as one of its members. When I tried a similar program in my machine with VC 6.0, it worked fine. Here is my code.

#include "stdafx.h"

struct params
{
int i;
int j;
};

DWORD WINAPI ThreadRoutine(LPVOID param)
{
((params*) param)->i = 1;
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.

params *p = new params();
p->i = 0;
p->j = 0;

DWORD ID = 0;
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadRoutine, (LPVOID) p, 0, &ID);
while (p->i == 0);

MessageBox(0, "Yes", 0, 0);
return 0;
}


I think I have done (atleast roughly) what you intend to do. I get the messagebox promptly. If I have not caught your point please let me know.
-TeeJBee

msanford
March 26th, 2003, 01:10 PM
TeeJBee -- Yes that is exactly what I am trying to do. Matter of fact is exactly what I am doing (pretty much). Your example works for me also, but In function I do quite a bit of processing and setup before setting the hwnd variable.

I slept on it all night and I realized that possibly Kheun's answer is right. The reason that it works with the cout is because this forces the intial thread to yield and wait for the display giving the other function time to reach the point where the variable is set. I too am sure that this is no longer an optimization problem. In the end using Sleep made it work properly.

Thank you both for your responses.

poccil
March 26th, 2003, 01:45 PM
I assume you're waiting for the thread to exit. Call WaitForSingleObject on the thread handle returned by CreateThread.

msanford
March 26th, 2003, 02:44 PM
no, no, no If I just wanted to wait for the thread to exit what would be the point of having a thread I could just call the function. The Sleep thing only works once in a while ARRG. Am I doing something completly wrong?

Here is what the CreatePrgWindow function is:

extern "C" __declspec(dllexport) int CreateProgressBox(long param)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
PBar* thePBar;
struct FunctionParams
{
char* caption;
char* text;
int ntimes;
int* ptrStop;
HWND hwnd;
};
FunctionParams* fparam=(FunctionParams*)param;
thePBar=new PBar(fparam->caption, fparam->text, fparam->ntimes, 0);
thePBar->Create(IDD_PBAR, 0);
fparam->hwnd=thePBar->GetSafeHwnd();
thePBar->DoModal();
delete thePBar;
return true;
}

cvogt61457
March 26th, 2003, 03:07 PM
Does the worker thread reside in the DLL also?

If the worker thread and the progress dialog both reside in the
DLL, try sending a message to the dialog from the thread using
PostMessage for updating the progress dialog. When the
thread has completed, send a different message to the progress
dialog to close. Use registered messages instead of using
WM_USER.

From what I see, the call to CreateProgressBox does not return
until the worker thread has completed.


BTW: Are you using CreateThread, beginthread or
AfxBeginThread?
Search the MSDN library for "beginthread" and look at the
article "C Run-Time Library Functions for Thread Control."
I don't think that this is a problem here, but you never know.

Can you attach you progress bar and the worker thread code?
Remove any specific code and put sleep() in place.

msanford
March 26th, 2003, 03:19 PM
Okay maybe I should explain myself better. What I am trying to do is display a progress dialog box while I loop on a c function. Here are all the important functions, I have excluded the loading of the library and declration of the PBar class. I also have the DoModal function for the PBar class I wrote:


void ShowProgressDialog(FunctionParams* f)
{
fparams=f;
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CreatePrgWindow, (LPVOID)fparams, 0, &dwThreadId);
while (fparams->hwnd==0)
Sleep(10);
}

void IncrementProgressDialog()
{
if (fparams!=0)
PostMessage(fparams->hwnd, WM_APP+100, 0, 0);
}

void CloseLibraryFunctions()
{
if (hLib!=0)
FreeLibrary((HMODULE)hLib);
}

void main()
{
int i=0;

if (!LoadLibraryFunctions())
{
cout << "Error Loading Library Functions" << endl;
return;
}

ShowProgressDialog(&fparam);

for (i=0; i<10; i++)
{
cout << "Running function " << i << endl;
FunctionToRun();
IncrementProgressDialog();
}
cout << "Press any key to Exit\n" << flush;
getch();
CloseLibraryFunctions();
}
//And here is the domodal function within the PBar class:

int PBar::DoModal()
{
MSG msg;
ShowWindow(SW_SHOW);
while (1)
{
if (PeekMessage(&msg, this->GetSafeHwnd(),0,0,PM_REMOVE))
{
CString mesg;
mesg.Format("Unbknown Message recieved %i",msg.message);
switch (msg.message)
{
case WM_QUIT:
case WM_CLOSE:
goto EXIT;
case WM_APP+100:
pbar.SetPos(curPos);
pbar.UpdateData();
curPos++;
break;
default:
DispatchMessage( &msg );
}
}
}
EXIT:
DestroyWindow();
return 0;
}



I thank everybody again for thier help. I am kind of new to win32 so I may have made a lot of stupid mistakes.