简体   繁体   English

在 Win32 中管理应用程序关闭的技术

[英]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.我们有一个使用 WTL(Windows 模板库)编写的 Win32 应用程序,我正在寻找退出应用程序的模式。 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)我正在处理的问题是应用程序中的某些视图包含可能需要一些时间(以 1 到 2 秒为单位)来销毁(即等待线程退出等)的资源

Win32 seems to support two main lifecycle messages, WM_CLOSE and WM_DESTROY. Win32 似乎支持两个主要的生命周期消息,WM_CLOSE 和 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_CLOSE 似乎是您要向窗口发送的消息,通知它们有关闭应用程序的请求,并让您有机会决定是否继续关闭。 WM_DESTROY, is when take down is occurring and should just be cleaning up. WM_DESTROY,是发生拆除的时候,应该只是清理。

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.示例:主窗口收到 WM_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_CLOSEWM_DESTROY的假设不正确。

WM_CLOSE is a request to close a window. WM_CLOSE是关闭窗口的请求。 It happens when the user clicks the 'X', or presses Alt+F4 for example.例如,当用户单击“X”或按 Alt+F4 时会发生这种情况。 The default handler for WM_CLOSE initiates the destruction of the window that received the close request. WM_CLOSE的默认处理程序启动销毁接收关闭请求的窗口。

WM_DESTROY is part of the message cascade happening when a window is actually destroyed ( DestroyWindow function). WM_DESTROY是实际销毁窗口时发生的消息级联的一部分( DestroyWindow函数)。 It is not the last message to be received during window destruction, that would be WM_NCDESTROY .不是窗口销毁期间收到的最后一条消息,它是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.所以它需要 UI 线程终止。 Which requires its message loop to terminate.这需要它的消息循环终止。

The message loop terminates when it decides to break out of its while loop.消息循环在决定退出其 while 循环时终止。 The trick here is that GetMessage returns false upon receiving WM_QUIT .这里的技巧是GetMessage在接收到WM_QUIT时返回false 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. WM_QUIT是调用PostQuitMessage的结果,在运行良好的应用程序中,它发生在应用程序主窗口的WM_DESTROY处理程序中。 This call to PostQuitMessage is the application programmer's responsibility, and you can do whatever you want here.PostQuitMessage的调用是应用程序程序员的职责,您可以在这里做任何您想做的事情。

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).当用户单击 X(或 Alt+F4)时, WM_CLOSE被发送到窗口。 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.您可以忽略它,或者(通常)调用DestroyWindow ,然后窗口接收WM_DESTROY ,您可以在其中调用 PostQuitMessage 来中断消息循环。

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.应用程序在WinMain返回(或ExitProcess()调用)之前不会终止,而不是在消息循环中断时终止。 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. WM_CLOSE是 Windows 告诉应用程序代码用户想要关闭一个窗口。 The default behavior, what you get if DefWindowProc fields the message, is for WM_CLOSE to cause the window to be destroyed.默认行为,如果DefWindowProc字段消息,你会得到什么,是WM_CLOSE导致窗口被销毁。 Destroying the window will lead to WM_DESTROY being posted to the window.销毁窗口将导致WM_DESTROY被发布到窗口。 A typical pattern is to post WM_QUIT from the WM_DESTROY handler if the window in question is the application's main window.如果所讨论的窗口是应用程序的主窗口,则一个典型的模式是从WM_DESTROY处理程序发布WM_QUIT

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 .您不能从WM_CLOSE销毁窗口,也不能从WM_DESTROY PostQuitMessage销毁。 This is all up to you.这完全取决于你。

Example: Main window receives WM_CLOSE because user clicks on close.示例:主窗口收到 WM_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.因此,如果您不想退出应用程序,可以允许从WM_CLOSE销毁窗口,但不要从该窗口的WM_DESTROY处理程序发布退出消息。 Post whatever custom messages (say) you need to cleanup resources from WM_CLOSE and only when that all completes call PostQuitMessage .发布您需要从WM_CLOSE清理资源的任何自定义消息(例如),并且只有在所有这些都完成时才调用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.但是,请注意,启动 WM_CLOSE 的是用户,因此当发生这种情况时,您的应用程序最好立即关闭该窗口,否则会感觉关闭。

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.我会让WM_CLOSE处理程序向用户显示“请稍候”消息,然后异步启动所需的任何关闭逻辑。 Do not call DefWindowProc() or DestroyWindow() yet.暂时不要调用DefWindowProc()DestroyWindow()

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.当所有关闭任务完成后,关闭“请稍候”消息,并销毁应用程序窗口,指示消息循环退出,如其他答案所述。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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