CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 25

Hybrid View

  1. #1
    Join Date
    Aug 2006
    Posts
    515

    Eliminate PumpMessage()

    It is said that true Win32 should never use a function like PeekAndPump() below to make it responsive, instead threads should be used.
    Code:
    void PeekAndPump()
    {
        MSG msg;
        while (::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE)) 
        {
            AfxGetThread()->PumpMessage();
        }
    }
    Following the principal, I am loading a large file in a worker thread and posting its data to the main thread. It is working beautifully but because the worker thread is busy in continuous reading loop, the main window still doesn't get a chance to update data and is not as responsive. My first thought was that it can still use PeekAndPump()!? but I added a Sleep(5) to the loop in worker thread and the GUI is much smoother now but the delay also adds to file loading as well with each iteration in the loop. I am going to try introducing delay after 50 iterations now instead of each one but am I am on the right track? I want to the main GUI to be very responsive and not waste much time with file loading as well. PeekAndPump() is out right? Is delay function the only way?
    Last edited by zspirit; February 19th, 2010 at 05:10 PM.

  2. #2
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: Eliminate PumpMessage()

    Quote Originally Posted by zspirit View Post
    Following the principal, I am loading a large file in a worker thread and posting its data to the main thread. It is working beautifully but because the worker thread is busy in continuous reading loop, the main window still doesn't get a chance to update data and is not as responsive. My first thought was that it can still use PeekAndPump()!? but I added a Sleep(5) to the loop in worker thread and the GUI is much smoother now but the delay also adds to file loading as well with each iteration in the loop. I am going to try introducing delay after 50 iterations now instead of each one but am I am on the right track? I want to the main GUI to be very responsive and not waste much time with file loading as well. PeekAndPump() is out right? Is delay function the only way?
    Seems like you are working on a machine with a single core processor. Those are becoming rare for PCs.
    In any case, don't put delays in your worker thread. All it effectively does is limit the processor use of the worker thread. I think what you want is to run the worker thread in a lower priority. That way, your main thread will always get scheduled before the worker thread, thus making it more responsive.
    How are you creating the worker thread?
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  3. #3
    Join Date
    Aug 2006
    Posts
    515

    Re: Eliminate PumpMessage()

    I do have Core 2 CPU and tried it both on work as well as home PC (also Core 2), changed thread to priorities to THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST but I can never see a live filling of the list. Basically the windows show up and the list is empty (not updated) until full list is loaded. This rather defeat the purpose of the thread because I want to see the data which is already loaded by the file.

    My objective is that even the file is very large and can take 30 seconds or more to load, the user should still start seeing the data right away and the rest of the list will be loaded in background while the user can work with already opened file.

    Delay sound even worse than PeekAndPump() but how can I make this work without these?

    Here is how I create the thread:
    Code:
    AfxBeginThread(LoadFileThread, (LPVOID) &tp, THREAD_PRIORITY_IDLE);

  4. #4
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: Eliminate PumpMessage()

    Quote Originally Posted by zspirit View Post
    I do have Core 2 CPU and tried it both on work as well as home PC (also Core 2), changed thread to priorities to THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST but I can never see a live filling of the list. Basically the windows show up and the list is empty (not updated) until full list is loaded. This rather defeat the purpose of the thread because I want to see the data which is already loaded by the file.

    My objective is that even the file is very large and can take 30 seconds or more to load, the user should still start seeing the data right away and the rest of the list will be loaded in background while the user can work with already opened file.

    Delay sound even worse than PeekAndPump() but how can I make this work without these?
    Perhaps the problem is that your user interface thread is busy. How often are you posting update messages from your worker thread to your GUI thread (couple of times per second, thousand times per seconds,...)?
    Also what do you do to handle the update message? If you are refilling a list box e.g. that could take a reasonable amount of time. If that has to happen a thousand times per second, your GUI thread will get clogged.

    The fact that you don't see a "live filling" of the list could be because you need to Invalidate() the list box after you update it.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  5. #5
    Join Date
    Aug 2006
    Posts
    515

    Re: Eliminate PumpMessage()

    Quote Originally Posted by D_Drmmr View Post
    Perhaps the problem is that your user interface thread is busy.
    It has to fill the list and show the results so yes it is busy doing that however it is not excessive, just the regular load of filling a list with one row in each message posted.
    Quote Originally Posted by D_Drmmr View Post
    How often are you posting update messages from your worker thread to your GUI thread (couple of times per second, thousand times per seconds,...)?
    I would say about thousand. The thread reads each record from file and post the data to the main thread, than it reads the next record and post data again and so on until all file is read. This is the loop. pseudo code
    Code:
    char * bfr = new 500;
    file->Read(bfr, 500);
    ::PostMessage(hWnd , IDM_NEW_RECORD, (WPARAM) bfr, (LPARAM)0);
    Quote Originally Posted by D_Drmmr View Post
    Also what do you do to handle the update message? If you are refilling a list box e.g. that could take a reasonable amount of time. If that has to happen a thousand times per second, your GUI thread will get clogged.
    The main thread responds to the message above by inserting the item in the Listview at next location (it only insert this item as rest are already there from previous thread messages). I think Invalidate() is automatically applied by InsertItem(). Even though one row is added in response to each message it still needs some amount of time to update the addition to listview/scrollbar visually. In my view this time probably increases as the items in the list increases as GUI has to manage more active data. But again I expect this is and it is what I am trying to smooth out so main thread can display up to date data and read thread keep digging it from file. Can't threads help out here?
    Quote Originally Posted by D_Drmmr View Post
    The fact that you don't see a "live filling" of the list could be because you need to Invalidate() the list box after you update it.
    I thought additional Invalidate() could be excessive but I still tried that to see if changes anything but it doesn't.

  6. #6
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: Eliminate PumpMessage()

    Quote Originally Posted by zspirit View Post
    I would say about thousand. The thread reads each record from file and post the data to the main thread, than it reads the next record and post data again and so on until all file is read.
    [...]
    The main thread responds to the message above by inserting the item in the Listview at next location (it only insert this item as rest are already there from previous thread messages). I think Invalidate() is automatically applied by InsertItem(). Even though one row is added in response to each message it still needs some amount of time to update the addition to listview/scrollbar visually. In my view this time probably increases as the items in the list increases as GUI has to manage more active data. But again I expect this is and it is what I am trying to smooth out so main thread can display up to date data and read thread keep digging it from file. Can't threads help out here?
    The problem is that you are posting update messages faster than what is useful. No human being can track 1000 updates per second; 10 per second will already look quite "smooth". So instead of posting a message for every 500 bytes, do so for every 10000 bytes. That'll probably make your application more responsive.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  7. #7
    Join Date
    Jan 2002
    Location
    Houston, TX
    Posts
    1,421

    Re: Eliminate PumpMessage()

    Quote Originally Posted by zspirit View Post
    I think Invalidate() is automatically applied by InsertItem(). Even though one row is added in response to each message it still needs some amount of time to update the addition to listview/scrollbar visually.
    Although this may be true, the Invalidate() message is only processed when idle time permits.

    You could try using the UpdateWindow() method on your list control after each time you insert a record.

    Hope that helps.
    Be sure to rate those who help!
    -------------------------------------------------------------
    Karl - WK5M
    PP-ASEL-IA (N43CS)
    PGP Key: 0xDB02E193
    PGP Key Fingerprint: 8F06 5A2E 2735 892B 821C 871A 0411 94EA DB02 E193

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

    Re: Eliminate PumpMessage()

    Try Sleep(0) which should cause thread context switch. I remember I did this in one of my old programs, could not imagine that this is still relevant on modern processors...
    PeekAndPump may be used only in UI threads, I don't think it is relevant here.

  9. #9
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: Eliminate PumpMessage()

    Quote Originally Posted by zspirit View Post
    It is said that true Win32 should never use a function like PeekAndPump() below to make it responsive, instead threads should be used.
    Whoever said that is wrong. Threads have their advantage in certain situations but for little stuff like checking if a button is clicked or painting a window, a message pump is easier to use and works perfectly well.

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