Cycle of processing / processing mouse messages

I wrote a multi-threaded program that does some thinking and outputs some diagnostic data along the way. I noticed that if I shake my mouse while the program is running, the program will run faster. Now I could go into detail about exactly how I type ... but I will stick in place because I noticed that in many other programs everything happens faster if the mouse moves, I wonder if this is some classic error that produced many people in which the message loop is somehow slowed down by a moving mouse.

EDIT: my "print" method looks like this ... I have an advanced edit control window for displaying text. When I want to print something, I'll add new text to the existing text inside the window and then redraw the window using SendMessage (, WM_PAINT, 0,0).

It's actually a little more complex, I have several rich edit control windows, one for each thread (4 threads on my 4-core PC). A rough outline of my "my_printf ()" looks like this:

void _cdecl my_printf(char *the_text_to_add)
{
    EnterCriticalSection(&my_printf_critsec);
    GetWindowText(...); // get the existing text
    SetWindowText(...); // append the_text_to_add
    SendMessage(...WM_PAINT...);
    LeaveCriticalSection(&my_printf_critsec);
}

      

I must point out that I have been using this printing method for many years in a multi-threaded program without even noticing any mouse interaction.

EDIT: Ok, here is my entire messageloop that runs on the root thread while the child threads do their job. In child threads, my_printf () are reporting their progress.

for(;;)
{
    DWORD   dwWake;
    MSG msg;

    dwWake = MsgWaitForMultipleObjects(
                            current_size_of_handle_list,
                            hThrd,
                            FALSE,
                            INFINITE,
                            QS_ALLEVENTS);

    if (dwWake >= WAIT_OBJECT_0 && dwWake < (WAIT_OBJECT_0 + current_size_of_handle_list))
    {
        int index;
        index = dwWake - WAIT_OBJECT_0;
        int j;
        for (j = index+1;j < current_size_of_handle_list;j++)
        {
            hThrd[j-1] = hThrd[j];
        }
        current_size_of_handle_list--;
        if (current_size_of_handle_list == 0)
        {
            break;
        }

    }
    else if (dwWake == (WAIT_OBJECT_0 + current_size_of_handle_list))
    {
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    else if (dwWake == WAIT_TIMEOUT)
    {
        printmessage("TIMEOUT!");
    }
    else
    {
        printmessage("Goof!");
    }
}

      

EDIT: Solved! It might be an ugly solution, but I just changed the timeout from infinite to 20ms, then in the if (dwWake == WAIT_TIMEOUT) section I changed printmessage ("TIMEOUT!"); for:

while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

      

I am not closing this question yet, because I would still like to know why the original code was not working on its own.

+2


source to share


8 answers


I see 3 problems here:

  • the documentation for WM_PAINT

    says: The WM_PAINT message is generated by the system and should not be sent by an application.

    Unfortunately I don't know a workaround, but I think SetWindowText () will take care of repainting the window, so this call might be useless.

  • SendMessage () is a blocking call and does not return until the message has been processed by the application. as drawing may take a while and your program will probably hang in your critical section, especially when considering my third point. PostMessage () will be much better here, since you have no reason for your window to be repainted "right now."

  • you use QS_ALLEVENTS

    in MsgWaitForMultipleObjects (), but this mask does NOT include the flag QS_SENDMESSAGE

    . so your SendMessage () call is probably being ignored and won't wake up your thread. you have to use QS_ALLINPUT

    .



can you test the behavior of your application with INFINITE timeout and the above three modifications included?

+3


source


Well, I can't fully help you because we don't have enough information, but I had a similar problem where my app wouldn't update unless I moved my mouse, or after some (non-insignificant) delay.

While researching the problem, I found that basically the GUI thread would sleep if no more messages were processed. Moving the mouse will create new windows that will be sent to windows, waking the thread from sleep.

My problem was that I was doing my processing in an OnIdle function (MFC, not sure about you), and that after doing the processing once, the thread would go to sleep.

I don't think this is your problem as you seem to be sending a Windows message (WM_PAINT) from your thread, which I didn't do in my case (which should wake up the gui thread), but maybe this can help you get to the right one direction to solve your problem?



Edit: I'm not much on this though, maybe there is a special case for WM_PAINT (for example, you forgot to call Invalidate or whatever, I'm not an expert in window programming), so maybe try sending another message like WM_USER. your application and see if it fixes your problem (this should definitely wake up, I think). A full call to the SendMessage function can also help.

Edit2: Ok, after seeing your comment on Kelly French above, you seem to have the same symptoms as me, so I would guess that for some reason your call to PostMessage doesn't seem to wake up the gui thread, or something else similar. What are you passing for the first argument to PostMessage? What I did in my case was to call PostMessage with the WM_USER, 0, 0 argument to my application. You can also try the PostThreadMessage variant by storing the current threadID of the main thread in a variable (see GetCurrentThreadId).

Also you can try to call Invalidate on your object. Windows keeps track of whether an object needs to be repainted and will not do it if it is not needed. I don't know if this overrides the direct WM_PAINT call or not.

Ok that's all I can think of. At least you've found a fix, even if it's not the most elegant one.

+1


source


If I recall correctly, WM_PAINT is a very low priority message and will only receive retransmission when the message queue is empty. Additionally, Windows will merge multiple WM_PAINT messages into one. I could see the movement of the mouse, which resulted in fewer redraw events, each of which handled a larger update, thus improving performance.

+1


source


Are you completely sure the program is actually faster? Or is it a result that gets updated more often?

0


source


Are you using SendMessage or PostMessage? I am curious if perhaps switching to something else would make things "better" in this particular environment.

Shot from developerfusion:

Theres another similar API that works exactly the same as SendMessage and that is the PostMessage API. Both require the same parameters, but the difference. When a message is sent to a window with SendMessage, the window procedure is called and the call to the program (or thread) waits for the message to be processed and responds back, and until that time the program does not resume processing. One thing is wrong with this approach, however, a program busy with lengthy instructions or programs hung and therefore no time to respond to the message in turn hang programs, because your program will wait for a response that will never arrive. The solution to this is to use PostMessage instead of SendMessage. Returning PostMessage to the calling program immediately without waiting for the thread to process the message, hence the hang-up program. Which one should you use,depends on your requirement.

0


source


Is your GUI window maximized? Does it happen if the mouse movement occurs over an application window or over some other window like another application or desktop? When the mouse moves over your application, mouse_move messages are sent to the message queue. This can wake up the thread or force the WM_PAINT message.

I doubt printing is actually faster. I suspect that increasing the number of messages triggered by mouse movement causes more window cancellation events, so text updates are more granular. When the mouse is not moving, is printing happening in large blocks, for example 20 characters versus 5 characters at a time?

Could you clarify what you mean by faster printing? Is it absolute, like 100 characters per minute versus 20 characters per minute? Or is it more like 100 characters per minute anyway, but they appear in blocks when the mouse is still?

0


source


I think it has something to do with the processing in the foreground and background. If the operating system thinks that your window is not the top priority, it pushes your work into the background. If you force the window to be on top, it will use all of its resources for your window and discard the other elements it is working on. Its real and it has been here since DOS. http://en.wikipedia.org/wiki/Foreground-background You can try calling at critical times in your code.

Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long

      

0


source


One possibility is that you can see the OS impact on thread priority / slowdown for certain GUIs.

I am assuming you have one GUI and Other Stuff thread and several worker threads. When there is no GUI activity, the Other Stuff stream falls back to a lower priority. When you wiggle the mouse or time out, the Other Stuff stream is given a higher priority.

Changing worker threads to a lower priority and then wiggling the mouse will confirm or deny that.

0


source







All Articles