CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Mar 2003
    Posts
    41

    This is Strange....

    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.
    Matthew Sanford

    "The man who doesn't read good books has no advantage over the man who can't read them."
    -- Mark Twain

  2. #2
    Join Date
    Oct 2002
    Location
    Singapore
    Posts
    3,128
    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.

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

  3. #3
    Join Date
    Nov 2001
    Posts
    69
    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.
    PHP Code:
    #include "stdafx.h"

    struct params
    {
        
    int i;
        
    int j;
    };

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

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

        
    DWORD ID 0;
        
    CreateThread(NULL0, (LPTHREAD_START_ROUTINEThreadRoutine, (LPVOIDp0, &ID);
        while (
    p->== 0);

        
    MessageBox(0"Yes"00);
        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

  4. #4
    Join Date
    Mar 2003
    Posts
    41
    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.
    Matthew Sanford

    "The man who doesn't read good books has no advantage over the man who can't read them."
    -- Mark Twain

  5. #5
    I assume you're waiting for the thread to exit. Call WaitForSingleObject on the thread handle returned by CreateThread.

  6. #6
    Join Date
    Mar 2003
    Posts
    41
    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:
    PHP Code:
    extern "C" __declspec(dllexportint CreateProgressBox(long param)
    {
        
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
        
    PBarthePBar;
        
    struct FunctionParams
        
    {
            
    charcaption;
            
    chartext;
            
    int ntimes;
            
    intptrStop;
            
    HWND hwnd;
        };
        
    FunctionParamsfparam=(FunctionParams*)param;
        
    thePBar=new PBar(fparam->captionfparam->textfparam->ntimes0);
        
    thePBar->Create(IDD_PBAR0);
        
    fparam->hwnd=thePBar->GetSafeHwnd();
        
    thePBar->DoModal();
        
    delete thePBar;
        return 
    true;

    Matthew Sanford

    "The man who doesn't read good books has no advantage over the man who can't read them."
    -- Mark Twain

  7. #7
    Join Date
    Aug 2001
    Location
    Texas
    Posts
    645
    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.

  8. #8
    Join Date
    Mar 2003
    Posts
    41
    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:

    PHP Code:
    void ShowProgressDialog(FunctionParamsf)
    {
        
    fparams=f;
        
    hThread CreateThread(NULL0, (LPTHREAD_START_ROUTINE)CreatePrgWindow, (LPVOID)fparams0, &dwThreadId);
        while (
    fparams->hwnd==0
            
    Sleep(10);
    }

    void IncrementProgressDialog()
    {
        if (
    fparams!=0)
            
    PostMessage(fparams->hwndWM_APP+10000);
    }

    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=0i<10i++)
        {
            
    cout << "Running function " << << 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(&msgthis->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.
    Matthew Sanford

    "The man who doesn't read good books has no advantage over the man who can't read them."
    -- Mark Twain

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured