Window message WM_SIZING sending incessantly when window resizing - c++

I make small game and have some problem with low priority window messages, that incessantly sending from system and block running game logic's code.
I create my message loop something like this:
bool Window::SystemRoutineAndCheckQuit() {
::MSG msg;
while( ::PeekMessage( &msg, nullptr, 0, 0, PM_REMOVE ) ) {
if( msg.message == WM_QUIT ) {
::UnregisterClass( registeredClassName, ::GetModuleHandle( nullptr ) );
DLOG( lg ) << "Exit from system loop" << DLOG_END;
return false;
}
::TranslateMessage( &msg );
::DispatchMessage( &msg );
}
return true;
}
//....
while( window.SystemRoutineAndCheckQuit() ) {
// do all render and logic
}
I.e. before every frame I wanna process all messages from windows and then, when queue will empty do all logic. I notice when window resizing I get same message WM_SIZING again and again and queue never will empty when mouse button still press (even when size of window don't change from previos call I receive message with same window coordinates). So it block execute my code.
Is there any other messages, that keep windows message queue don't empty and what is the best way to process all messages without some low priority, like WM_SIZING?
I test it on Windows 8.
PS: I need resize window, so I don't wanna disallow it by change style.
EDIT: sorry for incorrect description problem, but found what real happened (and why my previously attempt to fix it by limit number of processed messages, or by break message process when get same message two times in sequence will not success). From PeekMessage I get message WM_NCLBUTTONDOWN and after this message program don't return from ::DispatchMessage and block continue execution of thread until mouse will be released. And when program in DispatchMessage, my handler get repeatly WM_SIZING or WM_MOVING (independently what return from message handler function (result of DefWindowProc, TRUE (message was processed) or 0).

You could just process N messages before each frame.. where N is a limit you set between 1-10. That way you can process a reasonable number of events, then get onto your actual game logic.
It's conceivable that Windows may just generate the 'window sizing' message continually when the queue is empty, to make sure applications are aware the window is being resized.
(Maybe MS think applications might not know, maybe there's nothing else the user can do.. so MS want to hammer that single message.)

When DefWindowProc handles WM_SYSCOMMAND with either SC_MOVE or SC_SIZE in the wParam, it enters a loop until the user stops it by releasing the mouse button, or pressing either enter or escape. It does this because it allows the program to render both the client area (where your widgets or game or whatever is drawn) and the borders and caption area by handling WM_PAINT and WM_NCPAINT messages (you should still receive these events in your Window Procedure).
It works fine for normal Windows apps, which do most of their processing inside of their Window Procedure as a result of receiving messages. It only effects programs which do processing outside of the Window Procedure, such as games (which are usually fullscreen and not affected anyway).
However, there is a way around it: handle WM_SYSCOMMAND yourself, resize or move yourself. This requires a good deal of effort, but may prove to be worth it. Alternatively, you could use setjmp/longjmp to escape from the Window Procedure when WM_SIZING is sent, or Windows Fibers along the same lines; these are hackish solutions though.
I solved it (using the first method) this past weekend, if you're interested I have released the code to the public domain on sourceforge. Just make sure to read the README, especially the caveat section. Here it is: https://sourceforge.net/projects/win32loopl/

Related

How do I stop Windows from blocking the program during a window drag or menu button being held down?

I am novice with Win32, and I have been pursuing a problem (if it can be called a problem at all) with Windows blocking your program's flow during the event when a user grabs the window title bar and moves it around the screen.
I have no legitimate reason to solve this problem, except that it bothers me. A few possibilities include removing the frame altogether, but it seems an inconvenient hack. Some games (single player) do not find this a problem at all. I have read however, that multiplayer games might experience problems when the program freezes as it expects continuous flow of information and can be overwhelmed after such a delay.
I have tried adding this to my WindowProc
switch (uMsg)
{
case WM_SYSCOMMAND:
if (wParam == SC_CLOSE)
PostQuitMessage(0);
return 0;
...
...
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
And this seems a quick hack, except that when I mousedown over the close icon I can pull the mouse away and let go without closing the program, and during that time, when the close icon is held down, the program once again is blocked.
Furthermore, I do not know how to manually include the code necessary to move the window when the user clicks the titlebar and drags the mouse. For starters I do not know which uMsg's and wParam's to handle.
My question is then, how do I disallow blocking during the case when the user clicks down the exit button (or minimize/maximize buttons) while still handling the case when the mouse is clicked and released over the button, and how do I allow the user to move/drag the window without it blocking the program (or what message is sent when the title bar is clicked without it being a button or menu)?
I am creating the window with WS_SYSMENU | WS_MINIMIZEBOX.
I still want the program to respond to minimize, maximize, and exit commands.
If multi-threading can fix it, then that is interesting, but I wonder if I can get it to work on single-core processors. And I have read about hooks, but the MSDN page is still hard for me to interpret.
Why Is My App Freezing?—An Introduction to Message Loops & Threads
This phenomenon is not isolated to any particular message. It's a fundamental property of the Windows message loop: when one message is being processed, no other message can be processed at the same time. It's not exactly implemented this way, but you can think of it as a queue, where your app pulls the messages out of the queue to process in the reverse order that they are inserted.
Therefore, spending too long processing any message is going to suspend the processing of other messages, effectively freezing your application (because it cannot process any input). The only way to solve this problem is the obvious one: don't spend too long processing any one message.
Often that will mean delegating the processing to a background thread. You will still need to handle all messages on the main thread, and the background worker threads need to report back to the main method when they are finished. All interaction with the GUI needs to happen on a single thread, and that is almost always the main thread in your application (which is why it is often called the UI thread).
(And to answer an objection raised in your question, yes, you can operate multiple threads on single processor machines. You won't necessarily see any performance improvements, but it will make the UI more responsive. The logic here is that a thread can only do one thing at a time, but a processor can switch between threads extremely rapidly, effectively simulating doing more than one thing at a time.)
More useful information is available here in this MSDN article: Preventing Hangs in Windows Applications
Special Cases: Modal Event Processing Loops
Certain window operations on Windows are modal operations. Modal is a common word in computing that basically refers to locking the user into a particular mode where they cannot do anything else until they change (i.e. get out of that) modes. Whenever a modal operation is begun, a separate new message processing loop is spun up and message handling happens there (instead of your main message loop) for the duration of the mode. Common examples of these modal operations are drag-and-drop, window resizing, and message boxes.
Considering the example here of window resizing, your window receives a WM_NCLBUTTONDOWN message, which you pass to DefWindowProc for default processing. DefWindowProc figures out that the user intends to start a move or resize operation, and entered a moving/sizing message loop located somewhere deep in the bowels of Windows' own code. Thus, your application's message loop is no longer running because you've entered into a new moving/sizing mode.
Windows runs this moving/sizing loop as long as the user is interactively moving/sizing the window. It does this so that it can intercept mouse messages and process them accordingly. When the moving/sizing operation completes (e.g., when the user releases the mouse button or presses the Esc key), control will return to your application code.
It is worth pointing out that you are notified that this mode change has occurred via the WM_ENTERSIZEMOVE message; the corresponding WM_EXITSIZEMOVE message indicates that the modal event-processing loop has exited. That allows you to create a timer that will continue to generate WM_TIMER messages that your application can process. The actual details of how this is implemented are relatively unimportant, but the quick explanation is that DefWindowProc continues to dispatch WM_TIMER messages to your application inside of its own modal event processing loop. Use the SetTimer function to create a timer in response to the WM_ENTERSIZEMOVE message, and the KillTimer function to destroy it in response to the WM_EXITSIZEMOVE message.
I only point that out for completeness, though. In the majority of Windows apps that I've written, I've never needed to do that.
So, What Is Wrong With My Code?
Aside from all of that, the behavior you describe in the question are unusual. If you create a new, blank Win32 application using the Visual Studio template, I doubt you will be able to replicate this behavior. Without seeing the rest of your window procedure, I can't tell if you're blocking on any messages (as discussed above), but the part I can see in the question is wrong. You must always call DefWindowProc for messages that you do not explicitly process yourself.
In this case, you might be fooled into thinking that you're doing that, but WM_SYSCOMMAND can have lots of different values for its wParam. You only handle one of those, SC_CLOSE. All of the rest of them just get ignored because you return 0. That includes all of the window moving and resizing functionality (e.g. SC_MOVE, SC_SIZE, SC_MINIMIZE, SC_RESTORE, SC_MAXIMIZE, etc. etc.).
And there's really no good reason to handle WM_SYSCOMMAND yourself; just let DefWindowProc take care of it for you. The only time you need to handle WM_SYSCOMMAND is when you've added custom items to the window menu, and even then, you should pass every command that you do not recognize on to DefWindowProc.
A basic window procedure should look like this:
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CLOSE:
DestroyWindow(hWnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
It is also possible that your message loop is wrong. The idiomatic Win32 message loop (located near the bottom of your WinMain function) looks like this:
BOOL ret;
MSG msg;
while ((ret = GetMessage(&msg, nullptr, 0, 0)) != 0)
{
if (ret != -1)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// An error occurred! Handle it and bail out.
MessageBox(nullptr, L"Unexpected Error", nullptr, MB_OK | MB_ICONERROR);
return 1;
}
}
You do not need hooks of any kind. The MSDN documentation on these is very good, but you're right: they're complicated. Stay away until you have a better understanding of the Win32 programming model. It is a rare case indeed where you need the functionality provided by a hook.
If multi-threading can fix it, then that is interesting but I wonder
if I can get it to work on single-core processors. And I have read
about hooks, but the MSDN page is still hard for me to interpret.
You can use multiple threads on a single-core processor. Performance would be better on multi-core systems, but that shouldn't prevent you from writing multithreaded applications. Anyway, go for it.
By printing all messages sent to WindowProc it appears WM_NCLBUTTONDOWN is sent last before the block occurs. You could check the mouse location after this event occurs, but it seems an inconvenient way to solve a simple problem.

Prevent window movement

I currently have a small game which runs in a win32 window. I just noticed that when I hold the top of the window (the bar which has the closing button) it freezes my application. I would like to disable this as it manages to completely destroy my application (timers continue to count).
It seems that with even the most minimalistic settings for creation of the window it still has this feature. How can I disable this? I currently have:
HWND hWnd = CreateWindowW( L"Game",L"Game",
0x00000000L | 0x00080000L,
wr.left,
wr.top,
wr.right-wr.left,
wr.bottom-wr.top,
NULL,
NULL,
wc.hInstance,
NULL );
I read that my thread is ignored while dragging, if I am forced into using 2 threads could someone please provide a small example of usage?
Or should I stop the timers? (what message should I catch, and would it even be catched?)
Update
I am using instances of my time class to handle timings which looks something like:
Timer::Timer() {
__int64 frequency;
QueryPerformanceFrequency( (LARGE_INTEGER*)&frequency );
invFreqMilli = 1.0f / (float)((double)frequency / 1000.0);
StartWatch();
}
void Timer::StartWatch() {
startCount = 0;
currentCount = 0;
watchStopped = false;
QueryPerformanceCounter( (LARGE_INTEGER*)&startCount );
}
My Win32 message loop contains: mousemove, keyup and keydown.
When DefWindowProc handles WM_SYSCOMMAND with either SC_MOVE or SC_SIZE in the wParam, it enters a loop until the user stops it by releasing the mouse button, or pressing either enter or escape. It does this because it allows the program to render both the client area (where your widgets or game or whatever is drawn) and the borders and caption area by handling WM_PAINT and WM_NCPAINT messages (you should still receive these events in your Window Procedure).
It works fine for normal Windows apps, which do most of their processing inside of their Window Procedure as a result of receiving messages. It only effects programs which do processing outside of the Window Procedure, such as games (which are usually fullscreen and not affected anyway).
However, there is a way around it: handle WM_SYSCOMMAND yourself, resize or move yourself. This requires a good deal of effort, but may prove to be worth it. Alternatively, you could use setjmp/longjmp to escape from the Window Procedure when WM_SIZING is sent, or Windows Fibers along the same lines; these are hackish solutions though.
I solved it (using the first method) this past weekend, if you're interested I have released the code to the public domain on sourceforge. Just make sure to read the README, especially the caveat section. Here it is: https://sourceforge.net/projects/win32loopl/
Since the title bar to the user that he/she can move the window, you could remove that title bar and borders altogether. See "opening a window that has no title bar with win32" for an example.
When the game launches or is paused, you could show your own UI elements to allow the user to move the game window in these specific situations but only then.
You can check for the size/move loop using the WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE messages.

Should I use DirectInput or Windows message loop?

I'm working on a C++ DirectX 2D game and I need keyboard and mouse input.
Wikipedia says:
Microsoft recommends that new applications make use of the Windows message loop for keyboard and mouse input instead of DirectInput
So how should I use it?
I have a GameScreen class whice take care of the drawing and the updating(game logic), I call the Draw and the Update methods inside a windows message loop.
Thanks
Since you pretty much have to run a message pump in order to have a window, you might as well use that pump to handle keyboard and mouse input as well. It's entirely up to your pump whether you hand keyboard events on to a child window, you can handle them in the pump if you prefer.
Your typical message pump looks like this:
while (GetMessage(&msg, NULL, 0, 0))
{
if (WM_QUIT == msg.message)
break;
TranslateMessage(&msg); // post a WM_CHAR message if this is a WM_KEYDOWN
DispatchMessage(&msg); // this sends messages to the msg.hwnd
}
For a game, your pump might look more like this
while (true)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD))
{
bool fHandled = false;
if (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST)
fHandled = MyHandleMouseEvent(&msg);
else if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST)
fHandled = MyHandleKeyEvent(&msg);
else if (WM_QUIT == msg.message)
break;
if ( ! fHandled)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
// if there are no more messages to handle right now, do some
// game slice processing.
//
}
}
Of course, your actual pump will likely be even more complex than that, possibly with a MsgWaitForMultipleObjects so that you can wake periodically even if there a no messages to process, but immediatelly when there are messages.
DirectInput has been deprecated for good reasons. As fas as I know, it creates an extra thread and just queries Windows' Raw Input interface. For best performance, I'd use Raw Input directly.
If performance is not an issue for you (and I guess that's the case for a 2D game on current hardware), follow Microsoft's advice and use window messages, as described by John Knoeller.
FYI: Re John Knoeller's answer... a simplistic message pump looks like this:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
The WM_QUIT test that he included can NEVER be true because GetMessage returns zero when a WM_QUIT is received. However, testing for WM_QUIT in a PeekMessage loop is required because PeekMessage returns true/false whether a message was returned or not. Since GetMessage blocks until a message is returned, so it can have a different return value.
If the game has a single window, than as far as I can tell the distinction is purely a matter of taste. If however, you have (or are planning to have, or cannot positively rule out the option of having in the future) multiple windows, then windows messaging can get tiresome.
Problem is that by default keyboard/mouse messages are routed only to the window currently in focus, and typically in games you want to be able to switch focus (to a hi-score view, enemies on radar view or whatever) and still maintain interactivity. The easy solution would be for every module which requires keyboard/mouse input to query for it directly, and not rely on message forwarding - hence, DirectInput.
I can't say much about your specific scenario, of course - just my 2c.
Yes, the MSDN post is correct. Using windows messages you can use the multilanguage support (for any kind of keyboard the user may be using)/personal settings of the user (mouse right button instead of left), etc.. that you have to discard away to use DirectInput/XInput.
Only use those 2 for the gamepad/joystick support. For the rest just use the windows messages.
For the details i agree with the John Knoeller answer.
Use the-only use directinput under special circumstances
The nice thing about the Windows message loop used with getmessage is that it uses 0% cpu usage. If you are doing unprocessor intensive things such as waiting for a key from the user, collecting data from the user such as in a database or a tax program, or even a word processor, it makes sense just to use the Windows message with getmessage. I the all the above programs date is the process when the user presses a key.
All that the Windows message loop needs to process keys is for that program to be switched to. The mouse does not even need to be in the window.
Special circumstances-use directinput
If you need to:
1) Know when a key is pressed and released. You also may not want repeating keys detected as keypresses.
2) Process keys in the background when another program is switched to.
If either of the above is true, then use directinput.
If you're just collecting data from the user, then you will need to use the sleep command to suspend execution of the program. You want the program to have 0% cpu usage in the task manager if the program is just sitting there waiting for keys from the user.
Use the sleep function putting the program to sleep until you want to poll direct input for keys.
Therefore direct input just wastes programming time if you are doing a simple ordinary task of collecting keys from the user as you can see.
XInput is definitly the way to go. Low-Latency input is crucial to gameing and XInput ( replacement of DirectInput in the new DirectXSDKs ) is designed for exactly these use-cases.
Further you have support for gamecontrollers, joysticks, etc out of the box.

Mouse jiggling / message processing loop

I have written a multithreaded program which does some thinking and prints out some diagnostics along the way. I have noticed that if I jiggle the mouse while the program is running then the program runs quicker. Now I could go in to detail here about how exactly I'm printing... but I will hold off just for now because I've noticed that in many other programs, things happen faster if the mouse is jiggled, I wonder if there is some classic error that many people have made in which the message loop is somehow slowed down by a non-moving mouse.
EDIT: My method of "printing" is as follows... I have a rich edit control window to display text. When I want to print something, I append the new text on to the existing text within the window and then redraw the window with SendMessage(,WM_PAINT,0,0).
Actually its a bit more complicated, I have multiple rich edit control windows, one for each thread (4 threads on my 4-core PC). A rough outline of my "my_printf()" is as follows:
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 should point out that I have been using this method of printing for years in a non-multithreaded program without even noticing any interaction with mouse-jiggling.
EDIT: Ok, here's my entire messageloop that runs on the root thread while the child threads do their work. The child threads call my_printf() to report on 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!
This may be an ugly solution - but I just changed the timeout from infinite to 20ms, then in the if (dwWake == WAIT_TIMEOUT) section I swapped printmessage("TIMEOUT!"); for:
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
I'm not closing this question yet because I'd still like to know why the original code did not work all by itself.
i can 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 any workaround, but i think SetWindowText() will take care of repainting the window, so this call may be useless.
SendMessage() is a blocking call and does not return until the message has been processed by the application. since painting may take a while to be processed, your program is likely to get hanged in your critical section, especially when considering my 3rd point. PostMessage() would be much better here, since you have no reason to need your window to be repainted "right now".
you are using QS_ALLEVENTS in MsgWaitForMultipleObjects(), but this mask DOES NOT include the QS_SENDMESSAGE flag. thus your SendMessage() call is likely ignored and does not wake your thread. you should be using QS_ALLINPUT.
can you check the behavior of your application with an INFINITE timeout and the above 3 modifications included ?
If I remember correctly, WM_PAINT is a very low priority message, and will only get relayed when the message queue is otherwise empty. Also, Windows will coalesce multiple WM_PAINT messages into one. I could see the mouse movement resulting in fewer redraw events, each handling a larger update, thus improving performance.
Well I can't totally help you because we don't have enough info but I had a similar problem where my application would not refresh unless I moved the mouse or after some (not unsignificant) delay.
When investigating the problem I found that basically, the GUI thread will sleep if there is no more messages to process. Jiggling the mouse will create new windows messages to be sent to the windows, waking the thread from sleep.
My problem was that I was doing my processing in the OnIdle (MFC, not sure about you) function, and that, after doing the processing one time, the thread would go to sleep.
I don't think that is your problem since you seems to post a windows message (WM_PAINT) from your thread, what I wasn't doing in my case (which should wake up the gui thread) but maybe this can help you get in the right direction to solve your problem?
Edit: I though about it a little, maybe there is a special case for WM_PAINT (like you forget to call Invalidate or something, I'm not an expert in windows programming) so maybe try to post another message like WM_USER to your application and see if it fix your problem (this should be sure to wake up the gui thread I think). Also posting the full call to the SendMessage function could help.
Edit2: Well, after seeing your comment to Kelly French above you seems to have exactly the same symptoms I had so I would guess that, for whatever reason, your call to PostMessage do not seems to wake up the gui thread or something similar. What are you passing for first argument to PostMessage? What I did in my case was to call PostMessage with argument WM_USER, 0, 0 to my app. You can also try the PostThreadMessage variant while keeping the current threadID of the main thread in a variable (see GetCurrentThreadId).
Also you could try to call Invalidate on your object. Windows keeps memory of if an object need to be repainted and will not do it if it is not needed. I do not know if a direct call to WM_PAINT override this or not.
Well that's all I can think of. At least you found a fix even if it is not the most elegant.
Are you completely sure that the program really runs faster? Or is it output that is refreshed more frequently?
Are you using SendMessage or PostMessage? I'm curious if perhaps switching to the other will make things work "better" in this particular environment.
Taken from developerfusion:
There’s another similar API which
works exactly like SendMessage and
that is PostMessage API. Both require
same parameters but there’s a slight
difference. When a message is sent to
a window with SendMessage, the window
procedure is called and the calling
program (or thread) waits for the
message to be processed and replied
back, and until then the calling
program does not resume its
processing. One thing is wrong with
this approach however, that is if the
program that is busy carrying out long
instructions or a program that has
been hung and hence no time to respond
to the message will in turn hang your
program too because your program will
be waiting for a reply that may never
arrive. The solution to this is to use
PostMessage instead of SendMessage.
PostMessage on the otherhand returns
to the calling program immediately
without waiting for the thread to
process the message, hence saving your
program from hanging. Which of them
you have to use depends on your
requirement.
Is your GUI window maximized? Does it happen whether the mouse movement happens over your app window or over some other window like another app or the desktop? When the mouse moves over your app, the mouse_move messages get sent to your message queue. This may wake up the thread or be forcing a WM_PAINT message.
I doubt that the printing is actually going faster. I suspect that the increased number of messages caused by the mouse movement is forcing more window invalidation events so the text updates are happening on a more granular basis. When the mouse isn't being moved does the printing happen in larger blocks, say blocks of 20 characters vs 5 characters at a time?
Could you clarify what you mean by faster printing? Is it absolute, like 100 characters per minute vs 20 characters per minute? Or is it more like 100 characters per minute either way but they show up in blocks when the mouse is still?
One possibility is that you are seeing the effect of the OS doing thread priority boosting / retarding for certain GUI messages.
I am assuming you have one ”GUI & Other Stuff” thread, and multiple worker threads. When there is no GUI activity, the “Other Stuff” thread goes to a lower priority. When you wiggle the mouse or timeout, the “Other Stuff” thread goes to a higher priority.
Changing the worker threads to a lower priority and then wiggling the mouse, would confirm or refute this.
I think it has to do with processing in foreground and background. If the operating system thinks your window is not top priority it shifts your job to background. If you are forcing the window to be on top, it will put all its resources to work on your window and drops the other items it is working on. Its real and its been here since DOS. http://en.wikipedia.org/wiki/Foreground-background You might try calling the following at critical times in your code.
Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long

Avoiding "(Not Responding)" label in windows while processing lots of data in one lump

I occasionally need to process a large amount of data from one package off the network, which takes sufficiently long that when the user tries to interact with the application windows adds the "(Not Responding)" string to the window title. I am aware this is because the processing is being done within a call to handle a message (some way up the stack) and therefore is blocking the message pump. I'm also aware the ideal way to deal with this is to process the data asynchronously in a separate thread so the pump can continue running, however this is a LARGE desktop application which is single threaded from top to toe and safely spinning this processing off is not feasible in our time frame.
So with that in mind, is there by any chance a way I can at least avoid the "not responding" moniker (which to most users reads as "has crashed") by telling windows my application is about to be busy before I begin the work? I believe there is something along these lines when responding to a request to close, one can keep asking windows for more time to avoid it proclaiming that your not "closing in a timely fashion"
I should add this is a C++ MFC application.
I don't think the Windows API can help you here.
Alternatively, how about showing a dialog box with a progress bar and make it run in a separate thread?
A text like "This operation may take half an hour" on the dialog box may be appropriate too.
Ok, firstly I upvoted Frederick's post because like it or not, the second thread is probably the best way to go.
However, if you really don't want to go down this road, you could manually pump the message queue within your apps inner loop. Something like this;
int Refresh()
{
MSG msg;
if (PeekMessage (&msg, NULL, 0, 0,PM_NOREMOVE))
if ((msg.message == WM_QUIT)
||(msg.message == WM_CLOSE)
||(msg.message == WM_DESTROY)
||(msg.message == WM_NCDESTROY)
||(msg.message == WM_HSCROLL)
||(msg.message == WM_VSCROLL)
)
return(1);
if (PeekMessage (&msg, NULL, 0, 0,PM_REMOVE))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return(0);
}
This is actually a piece of code I used prior to rewriting something similar as a seperate thread. Basically I have a look at the queue, filter out unwanted messages, and post on the rest. It works to an extent, but caused some occasional nasty side effects, hence the rewrite.
You don't have to actually do anything with the messages from PeekMessage. Just call PeekMessage, you don't even have to remove anything from the queue or process it. As long as it is called every 5 seconds or so, it will cause windows to think the process is still responsive.
An alternative idea is to have a separate process/thread that will appear in the notification tray and inform the user that the process is busy waiting for an internal operation to complete. You'll see these in the later versions of Visual Studio, SQL Server Management Studio, etc.
Win32 has a method for this in user32.dll.
DisableProcessWindowsGhosting()
Disables the window ghosting feature for the calling GUI process. Window ghosting is a Windows Manager feature that lets the user minimize, move, or close the main window of an application that is not responding.
In addition to the above documented behavior, I also verified here (in a C# application) that this Win32 call also prevents the Not Responding label from appearing on the window as desired.
I found this via the C# answer to similar question here: https://stackoverflow.com/a/15380821/29152.
If you fork off a thread you're most likely worried about some other user action happening which may depend on the result of the long running operation (yeah, concurrency). So expanding on what Fredrick said, if you do spin off a new thread and put up a progress bar, you could lock the focus onto the progress bar to stop a user from interacting with the rest of the application. That should be enough to implement a really simple second thread without really having to worry about concurrency because you're essentially locking out the rest of the app by disabling user interation.
You'll need to interleave the processing with message handling somehow. If threads are out of the question, you might want to look at splitting the processing into multiple phases. One way to do this is to do some processing when you first receive the packet, then post a message to the application saying "continue processing here". When the application receives the "continue processing here" message, it will do some more processing, and either send another "continue processing here" message or finish up.
There are a couple of considerations though:
You need to make sure that the state of the application is consistent every time you post a message to yourself and defer to the message loop, as other message handling might happen in the mean-time. This can be done e.g. by only changing the state in the final processing phase.
Another packet might arrive while you are still processing the first packet. If changing the order of processing would be bad for the application, you could handle this by e.g. posting a "remind me to process this packet later" message when this happens.
I don't know whether this would be feasible within the design of your application, but it would be one way to solve the problem.
If you are unwilling to spawn a worker thread, but you can break the long-running task down into smaller parts, you can do the processing in MFC's CWinApp::OnIdle. This function gets called from within the message pump loop whenever there are no Windows messages waiting. As long as the work you do in each OnIdle call is sufficiently short, you keep your app responsive.
Assuming that it is the processing of the data that is taking up all the time and not the receiving (and you're serious about avoiding a thread - which is fine IMOHO) of the data you could:
In the function that you are currently handling the message, create a modal dialog that shows a "please wait" message (or make it hidden, small, whatever...). Copy (or send a pointer, etc...) the data you're processing to a member variable of that dialog.
In the modal dialog post a user-defined message to yourself to process the data.
In the dialog's message handler, handle one "unit" of work. Keep track what the next "unit" of work is. Post the same message again.
Repeat this post-message "loop" until done. Close your dialog.
The nature of the modal dialog will keep you're application "responsive", with minimal interruption or change to how the application worked previously. Reentrancy can be a problem with modal loops, especially if any of this is involved with a WM_PAINT message. (anyone ever assert inside painting code? good times, good times...)
The dialog could even have a cancel button if you'd like.
I encountered the exact same problem.
Since I dont consider the other answers appealing/straightforward I decided to post this.
Short description and some context:
I am saving data from a grid into a database, and this process can take a while. So I changed the saving method to an asynchronous method and had the same problem.
Then I came up with a simple solution:
//__ENABLE OR DISABLE MAIN DIALOG
void CMFCApplication1Dlg::enableMainDlg(bool enable)
{
this->EnableWindow(enable);
}
When starting the asynchronous method, I disable the main dialog.
This prevents the user from interacting with the main dialog (like starting another saving process which could result in thousands of SQL error messages if I wouldn't check if the saving process is already running...)
When the saving process is finished, I re-enable the main dialog.
Works like a charm, I hope this helps
One way to overcome your application from becoming unresponsive you need to tell the application to process messages from windows. When you are in your loop you can call
Application->ProcessMessages();
I had a similar issue with a win32 app that was waiting on a response from webservice using cpprest (Casablanca) api. My solution was to create a event and thread that does nothing but wait for the cpprest api and then release the thread once it recieves the signal:
DWORD WINAPI WaitForCasablanca(LPVOID n)
{
// Get the handler to the event for which we need to wait in
// this thread.
HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, false, "MyEvent");
if (!hEvent) { return -1; }
// Loop through and wait for an event to occur
// Wait for the Event
WaitForSingleObject(hEvent, INFINITE);
// No need to Reset the event as its become non signaled as soon as
// some thread catches the event.
CloseHandle(hEvent);
return 0;}
BOOL WINAPI DlgProc(HWND hDlg, UINT message, WPARAM,wParam, LPARAM lParam) ...
HANDLE hEvent = CreateEvent(NULL, false, false, "MyEvent");//create an event that will wait for casablanca ro authenticate
if (!hEvent) return -1;
// Create a Thread Which will wait for the events to occur
DWORD Id;
HANDLE hThrd = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WaitForCasablanca, 0, 0, &Id);
if (!hThrd) { CloseHandle(hEvent); return -1; }
makeCasablancaRequest(...);
SetEvent(hEvent); //casablanca has finished signal the event to terminate
WaitForSingleObject(hThrd, INFINITE); //wait for thread to die
CloseHandle(hThrd);
CloseHandle(hEvent);
...}
That got rid of the "program not responding" message for me. I believe the problem is the code that is getting the data is running in a thread too- only the main program doesn't know this- so as far as the system is concerned the main program is idling. You need an event and a thread that waits for the event to tell the system the program is waiting on data. I got the code from this tutorial: How to use WIN32 Event Kernel Object