CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9
  1. #1
    Join Date
    Dec 2005
    Posts
    52

    How to awake main UI thread from another thread?

    Briefly, my application contains a main UI thread, and an internal event loop. I overrode CWinApp::OnIdle to run my own event loop, it looks like,

    Code:
    BOOL CMyApp::OnIdle(LONG lCount)
    {
        // TODO: Add your specialized code here and/or call the base class
       
        if (CWinApp::OnIdle(lCount))
            return TRUE;
    
        if (mController)
    {
    		// run my own event loop
            mController->run();
        }
    
        // Tell framework we don't need any more idle time to avoid CPU overhead.
        return FALSE;
    }
    The controller::run simply checked out if there’s any internal event and processes it accordingly.

    The problem has occurred when there’s a http request. The use case was,
    1. if there’s a http request, I should process it via WinInet.
    2. WinInet will create a new thread in background, here allow me to call this thread as “Http thread”, to get data downloaded or do whatever it’s supposed to do. When it’s done with the job, it should call a callback which I supplied in step 1.
    3. In the callback, it posted an internal event to internal event queue, and ideally, controller should immediately process it.

    The point is that the main UI thread possibly goes into idle state after it started a http request, and OnIdle then never gets invoked if there’s no UI messages to awake UI thread. This resulted in that controller didn’t process our own event at all even if we already notified it http request done.

    I thought there’s a simple solution that posted a WM_NULL to main UI thread in http callback, but it didn’t perfectly work in my case, since
    1. In callback, actually in that http thread, AfxGetMainWnd returned NULL, so I can’t get main window handle and got nowhere to post WM_NULL.
    2. For portable issue, I’m not allowed to preserve a global hwnd referring to main window.

    Besides, I’m thinking about improve my event processing, e.g., fully control when and where to process events instead of using OnIdle, use some asynchronous measurement to avoid high CPU occupation. However, it rose up another problem, if my thread get blocked and is waiting for a http request, how could I promptly respond to UI messages?

    Any idea?

  2. #2
    Join Date
    Jul 2002
    Posts
    2,543

    Re: How to awake main UI thread from another thread?

    The real solution is to create worker thread (or threads) and make everything there, instead of using OnIdle function, which is kind of "Multithreading for dummies". Your question "if my thread get blocked and is waiting for a http request, how could I promptly respond to UI messages?" is not clear, please provide more information.

  3. #3
    Join Date
    Dec 2005
    Posts
    52

    Re: How to awake main UI thread from another thread?

    Hi Alex_F,

    My point is that after my main thread sent a http request and then it went into suspended state, since there's no any input event, next, when http thread notified main thread via an internal event, (I can't make it via a WM_NULL because I can't get main window handle in http thread and I can't preserve a global hwnd), how to awake main UI thread to make it run into OnIdle, finally have my own event loop continue to process events?

    thx.

  4. #4
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: How to awake main UI thread from another thread?

    Quote Originally Posted by LifeIsSuffering View Post
    how to awake main UI thread to make it run into OnIdle, finally have my own event loop continue to process events?
    By default, OnIdle( ) gets called when the UI thread is waiting for windows messages. So there isn't the concept of "waking up the ui thread to make it run OnIdle".

    I suspect your overridden OnIdle( ) isn't getting called because your mController->run( ) method never returns.

    At any rate, OnIdle( ) isn't really meant to perform work. It's only meant to do small amounts of work like updating UI states like menus and toolbar buttons.

    What you need to do, as Alex F suggested, is to create a worker thread and do the work there.

  5. #5
    Join Date
    Dec 2005
    Posts
    52

    Re: How to awake main UI thread from another thread?

    Quote Originally Posted by Arjay View Post
    By default, OnIdle( ) gets called when the UI thread is waiting for windows messages. So there isn't the concept of "waking up the ui thread to make it run OnIdle".

    I suspect your overridden OnIdle( ) isn't getting called because your mController->run( ) method never returns.

    At any rate, OnIdle( ) isn't really meant to perform work. It's only meant to do small amounts of work like updating UI states like menus and toolbar buttons.

    What you need to do, as Alex F suggested, is to create a worker thread and do the work there.
    OnIdle gets its returned value, from MSDN,
    Eventually, OnIdle finishes processing all its idle tasks and returns 0. This tells the message loop to stop calling OnIdle until the next message is received from the message queue
    That's the reason why I have to wake up main thread.

    I can't return TRUE all the time, that made 100% CPU.

    On the other side, running my own loop in another worker thread, I have to do much thread-safe work there which I'm thinking about the cost.

    thx.
    Last edited by LifeIsSuffering; February 23rd, 2010 at 02:12 AM.

  6. #6
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: How to awake main UI thread from another thread?

    Quote Originally Posted by LifeIsSuffering View Post
    On the other side, running my own loop in another worker thread, I have to do much thread-safe work there which I'm thinking about the cost.
    What cost are you referring to?

  7. #7
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: How to awake main UI thread from another thread?

    That's the reason why I have to wake up main thread.
    The golden rule #1: GUI thread is never let sleep/block/wait.

    By following this rule you never get trapped with the situation like you have. Following this rule itself is thinking about the cost of future being rescued and proactive prevention of need in that.
    Best regards,
    Igor

  8. #8
    Join Date
    Dec 2005
    Posts
    52

    Re: How to awake main UI thread from another thread?

    Quote Originally Posted by Arjay View Post
    What cost are you referring to?
    The cost required to change my application to multi-thread mode.

    Quote Originally Posted by Igor Vartanov View Post
    The golden rule #1: GUI thread is never let sleep/block/wait.

    By following this rule you never get trapped with the situation like you have. Following this rule itself is thinking about the cost of future being rescued and proactive prevention of need in that.
    Sure. Essentially, running my event loop in OnIdle was really bad design.

    Now, I must think about refactor app structure as early as possible.

    Thx all you guys.

  9. #9
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: How to awake main UI thread from another thread?

    Quote Originally Posted by LifeIsSuffering View Post
    The cost required to change my application to multi-thread mode.
    It isn't really that hard. If you have Display Signatures turned on in your control panel, you can see several multithreading articles that can help you get started.

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