Eliminate PumpMessage()
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 25

Thread: Eliminate PumpMessage()

  1. #1
    Join Date
    Aug 2006
    Posts
    508

    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 04:10 PM.

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

    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
    508

    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 2002
    Posts
    2,505

    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.

  5. #5
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,011

    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

  6. #6
    Join Date
    Aug 2006
    Posts
    508

    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.

  7. #7
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Posts
    12,050

    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.

  8. #8
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,011

    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

  9. #9
    Join Date
    Aug 2006
    Posts
    508

    Re: Eliminate PumpMessage()

    Quote Originally Posted by D_Drmmr View Post
    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.
    I appreciate your point of view but I would disagree here. If the main thread doesn't have time to process a single message (insert a single row) until the read thread is done, I don't know how can it find time to process inserting 500 records while the read thread is still in progress.

    These updates are not alterations that they might be meaningless in a second but they are simply inserting new rows and I think it is easily noticeable by any user and in fact it is this noticeability that I am trying to make it work. I am trying to let the user at least see the list loading in action rather than almost not responding/no repainting and blocked like feeling.

  10. #10
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,011

    Re: Eliminate PumpMessage()

    Quote Originally Posted by zspirit View Post
    If the main thread doesn't have time to process a single message (insert a single row) until the read thread is done
    How did you deduce that? Cause the display isn't updated? That just means that the control isn't redrawn, not that your message is not handled. My guess is it's not getting redrawn, because the message pump is full of update messages before any repaint message comes in.
    These updates are not alterations that they might be meaningless in a second but they are simply inserting new rows and I think it is easily noticeable by any user and in fact it is this noticeability that I am trying to make it work.
    Again, you won't notice the difference between 1 line being added 1000 times per second or 10 lines being added 100 times per second. That's biology (your eye/brain won't work that fast), it has nothing to do with programming. (Even your screen won't update 1000 times per second).

    Just give it a try. It can't be that hard to program.
    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

  11. #11
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Posts
    12,050

    Re: Eliminate PumpMessage()

    If you have thousands of records, you should be looking at a virtual list control.
    http://www.codeguru.com/cpp/controls...icle.php/c4151
    http://msdn.microsoft.com/en-us/libr...8VS.80%29.aspx

  12. #12
    Join Date
    Aug 2006
    Posts
    508

    Re: Eliminate PumpMessage()

    Quote Originally Posted by D_Drmmr View Post
    Just give it a try. It can't be that hard to program.
    I figured there is a short cut way I could try since you seem to have a point. In my test code I made the modification to post 1 message after 50 iterations rather than in each iteration so read thread is equally busy but the main thread does load the list live now So I guess I am a believer now Thank you! Now it makes my coding job a little more complicated..have to read bulk of records at once and pass/decipher!?

    I was sending the message to view via hWnd from the thread and view was doing document management but is there a way I can access/manage document from the thread now to break the large chunk in pieces at the spot and place it in document?

    Quote Originally Posted by GCDEF View Post
    If you have thousands of records, you should be looking at a virtual list control.
    I am already using custom draw and LVN_GETDISPINFO notification, that should do right or does owner draw does even more? my listview is not storing any data just a pointer to it.
    Last edited by zspirit; February 22nd, 2010 at 02:17 PM.

  13. #13
    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

  14. #14
    Join Date
    Aug 2006
    Posts
    508

    Re: Eliminate PumpMessage()

    Quote Originally Posted by krmed View Post
    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.
    Actually I had to remove the extra Invalidate() call I put in the message handler because it was excessive as I thought and caused flicker. It worked better without it.

  15. #15
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Posts
    12,050

    Re: Eliminate PumpMessage()

    Quote Originally Posted by zspirit View Post
    I am already using custom draw and LVN_GETDISPINFO notification, that should do right or does owner draw does even more? my listview is not storing any data just a pointer to it.
    There's more to it than that. It's been a while since I set one up so I don't remember the details, but from the sound of your problem, you don't have it implemented correctly.

Page 1 of 2 12 LastLast

Posting Permissions

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


Azure Activities Information Page

Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center