2

When I run this code, the text is updated AFTER the message box in the thread is popped.

void PnlOptions::ClickHandler() {
    SetWindowText(txt_progress_, "CLASS MEMBER FUNCTION");

    HANDLE hThread = (HANDLE) _beginthreadex(0, 0, &ThreadProcess, 0, CREATE_SUSPENDED, 0);

    ResumeThread(hThread);
    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);
}

unsigned int __stdcall ThreadProcess(void * data0) {
    MessageBox(NULL, "THREAD FREE FUNCTION", "Alert", MB_OK);
}

I thought it was because

If the thread is created in a runnable state (that is, if the CREATE_SUSPENDED flag is not used), the thread can start running before CreateThread returns and, in particular, before the caller receives the handle and identifier of the created thread.

but using a non-suspended thread: same result.

Also tried:

  • Using CreateThread

  • Changing thread priority

  • Using SendMessage instead of SetWindowText

  • PeekMessage

Why does the thread start before the UI is updated?


Declarations:

pnl_options.h:

unsigned int __stdcall ThreadProcess(void *);

public PnlOptions:
     void Init(HWND);
     void ClickHandler();

private:
     HWND txt_progress_;

pnl_options.cpp (other than above code):

 void PnlOptions::Init(HWND hwnd0) {
    txt_progress_ = CreateWindowEx (0,
        TEXT("EDIT"), "Press \"GO\" to process all selected files.",
        SS_LEFT | SS_CENTERIMAGE | WS_VISIBLE | WS_CHILD,
        0, 0, 0, 0,
        hwnd0, (HMENU) IDT_PROGRESSTEXT, NULL, NULL
        );   
 }
Ben
  • 54,723
  • 49
  • 178
  • 224
  • I stupidly deleted my similar question asked several hours ago because I thought I had the answer. To those of you who have read it every time, my apologies. As I keep simplifying, turns out the question isn't going away, and now I'm getting "curioser and curioser", to quote Lewis Carroll. – Ben Nov 13 '12 at 11:05
  • Who is calling "ClickHandler"? – pagra Nov 13 '12 at 11:12
  • @patriiice - A button that sends WM_COMMAND to the main message loop. – Ben Nov 13 '12 at 11:17
  • So strange that I did a quick MFC application doing the same but it's behaving as expected, so not as yours. Are you using any framework? Maybe there is some important information missing about context... – pagra Nov 13 '12 at 11:36
  • Hmmm. No, but this is happening in a class outside of the main entry point file. It's a class that handles click options, I want it to run a progress bar and other stuff. `ClickHandler` is a member function, `ThreadProcess` is a free function, `txt_progress_` is a member variable. – Ben Nov 13 '12 at 11:42
  • `Are you using any framework?` I am using the Boost libraries for regex - does that count? – Ben Nov 13 '12 at 11:56

3 Answers3

1

I reproduced this behavior and it seems that there is a kind of deadlock between the EDIT control and his parent window because of a posted WM_PAINT message.

"Curioser", it works if you replace the EDIT with a STATIC control.

I don't have real explanation/solution for this, so it's more a clue than an answer...

PS: Note that SS_LEFT and SS_CENTERIMAGE are not valid for an EDIT control, use ES_* defines instead.

pagra
  • 665
  • 4
  • 11
  • Had to put this project on the back burner for a while, but now it's cooking again. Thanks for the repro, I'm glad I'm not crazy! And very helpful tips too. – Ben Nov 22 '12 at 00:49
  • For now I'll call `RedrawWindow(txt_progress_, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);` right after `SetWindowText()` as a workaround. Wouldn't have found it though without your detective work. Cheers. – Ben Nov 22 '12 at 00:50
0

You need to let the event loop roll before waiting for the other thread. In .NET it would be Applicaiton.DoEvents(). Search with that, SO seems to have bunch of related questions...

hyde
  • 60,639
  • 21
  • 115
  • 176
  • I've tried `PeekMessage` on the event, similar to http://stackoverflow.com/questions/1415095/doevents-equivalent-for-c - no luck. – Ben Nov 13 '12 at 11:39
0

SetWindowText sends a message in order to update the windows text, and the message will be processed in your message loop when it processes the message queue.

However, you're blocking in ClickHandler (via the call to WaitForSingleObject) which means that the message queue won't be processed until you return from ClickHandler

Sean
  • 60,939
  • 11
  • 97
  • 136
  • I thought `SendMessage` blocked already, before the other block? `The SendMessage function calls the window procedure for the specified window and does not return until the window procedure has processed the message.` – Ben Nov 13 '12 at 11:18
  • The documentation does SetWindowText (http://msdn.microsoft.com/en-gb/library/windows/desktop/ms633546%28v=vs.85%29.aspx) doesn't mention SendMessage anywhere... – Sean Nov 13 '12 at 11:27
  • Also, have you tried using SendMessage(WM_SETTEXT) instead of SetWindowText, just to see what happens? – Sean Nov 13 '12 at 11:30
  • I've tried this same thing with `SendMessage` and the behavior is the same (I'll add to the list of things tried). – Ben Nov 13 '12 at 11:32