简体   繁体   中英

Techniques for managing application shutdown in Win32

We have a Win32 application written using WTL (Windows Template Library), and I'm looking for patterns for exiting the application. The issue that I'm dealing with is that some of the views in the application contain resources which may take some time (measured in 1 to 2 seconds), to destroy (ie waiting for a thread to exit, etc)

Win32 seems to support two main lifecycle messages, WM_CLOSE and WM_DESTROY. WM_CLOSE seems to be the message you want to send windows to notify them that there is a request to close the application, and gives you the opportunity to decide on whether or not to continue to close. WM_DESTROY, is when take down is occurring and should just be cleaning up.

The question is, how would you handle a case where you want to keep the message loop running, while shutting down the application.

Example: Main window receives WM_CLOSE because user clicks on close. Let's say you don't need to prompt the user for exiting, but you then notify all of your views that a close is occuring. Let's also say that at this point, you don't want to exit the application because you need to clean up some resources, which may take a second or two, and you want the interaction to be asynchronous.

How would you notify the main window when all of the child views have completed their shutdown processes? To be more specific, is there any standard message for notifying parents that you are done cleaning up?

Your assumptions about WM_CLOSE and WM_DESTROY are incorrect.

WM_CLOSE is a request to close a window. It happens when the user clicks the 'X', or presses Alt+F4 for example. The default handler for WM_CLOSE initiates the destruction of the window that received the close request.

WM_DESTROY is part of the message cascade happening when a window is actually destroyed ( DestroyWindow function). It is not the last message to be received during window destruction, that would be WM_NCDESTROY .

Destroying the application's main window neither terminates the message loop, nor does it terminate the application.

The application terminates when all non-background threads terminate. So it requires the UI thread to terminate. Which requires its message loop to terminate.

The message loop terminates when it decides to break out of its while loop. The trick here is that GetMessage returns false upon receiving WM_QUIT . WM_QUIT is a result of calling PostQuitMessage , which, in a well-behaved application, happens in the WM_DESTROY handler of the application's main window. This call to PostQuitMessage is the application programmer's responsibility, and you can do whatever you want here.

In fact, you can also simply place your cleanup work after the message loop, before the main thread terminates.

All these are conventions, they have nothing to do with actual application shutdown.

WM_CLOSE is sent to the window when the user clicks X (or Alt+F4). You can ignore it, or (usually) you call DestroyWindow , then the window receives WM_DESTROY in which you can call PostQuitMessage to break the message loop.

Nobody forces you to actually break the message loop. There is no actual shutting down involved.What you will do after that is entirely up to the code. The application is not terminated until WinMain returns (or ExitProcess() called), not when the message loop is broken. You can start another message loop right away.

It's just that usually, most applications have one main window and, therefore, closing it is taken as the closing of the application.

WM_CLOSE is Windows telling the application code that the user wants to close a window. The default behavior, what you get if DefWindowProc fields the message, is for WM_CLOSE to cause the window to be destroyed. Destroying the window will lead to WM_DESTROY being posted to the window. A typical pattern is to post WM_QUIT from the WM_DESTROY handler if the window in question is the application's main window.

A key thing to understand is that none of this has to happen this way. You can not destroy the window from WM_CLOSE and you can not PostQuitMessage from WM_DESTROY . This is all up to you.

Example: Main window receives WM_CLOSE because user clicks on close. Let's say you don't need to prompt the user for exiting, but you then notify all of your views that a close is occuring. Let's also say that at this point, you don't want to exit the application because you need to clean up some resources

So if you don't want to exit the application maybe allow the window to be destroyed from WM_CLOSE but don't post the quit message from that window's WM_DESTROY handler. Post whatever custom messages (say) you need to cleanup resources from WM_CLOSE and only when that all completes call PostQuitMessage . Or something similar to this. There is not one right way; however, just note that it is the user who is initiating WM_CLOSE so when that happens your application better appear to close that window immediately or it will feel off.

The question is, how would you handle a case where you want to keep the message loop running, while shutting down the application.

I would have the WM_CLOSE handler display a "Please wait" message to the user, and then asynchronously initiate whatever shutdown logic is needed. Do not call DefWindowProc() or DestroyWindow() yet.

Let the message loop run normally while the shutdown logic is doing its thing in the background.

When all shutdown tasks are finished, dismiss the "Please wait" message, and destroy the application window, signalling the message loop to exit, as explained by the other answers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM