Delphi - 当应用程序退出时,未释放(但终止)的线程会发生什么?
我有多线程应用程序,当应用程序结束时遇到了一个小问题:我可以通过在 Form1.OnDestroy
事件处理程序中调用 TThread.Terminate
方法来正确终止线程,但是终止确实需要一些时间,因此我无法释放内存(通过 TThread.Free 方法)。 不幸的是,由于某些其他原因,我必须将 TThread.FreeOnTerminate 属性设置为 false,以便线程对象在线程终止后不会自动销毁。
我的问题可能有点傻,我早就应该知道了,但是这样可以吗,线程会自动销毁(因为应用程序刚刚结束),还是有问题,内存会“丢失” ?非常感谢您的解释。
I have multithreaded application and I've got a little problem when application ends: I can correctly terminate the thread by calling TThread.Terminate
method in Form1.OnDestroy
event handler, but the termination does take some time and so I can't free the memory (by TThread.Free
method).
Unfortunately for some other reason I must have TThread.FreeOnTerminate
property set to false, so the thread object isn't destroyed automatically after thread termination.
My question is probably a little silly and I should have known it a long time ago, but is this ok and the thread will be destroyed automatically (since the application just ends), or is it a problem and the memory would be "lost"? Thanks a lot for explanation.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您应该等待线程终止,然后再开始关闭应用程序的其余部分,否则共享资源可能会在线程脚下被释放,可能会导致一系列访问冲突。等待线程终止后,您可以释放它。事实上,这就是
TThread
析构函数为您所做的事情。如果没有共享资源,那么当然,就让它自己消亡吧。即使线程在主线程之后终止,所需要的只是所有线程退出以使程序终止。与线程对象关联的任何内存都将被清理并与其他所有内容一起返回给操作系统。
但是,要小心!如果您的线程需要一段时间才能退出,则可能会导致僵尸进程坐在那里,在没有 GUI 的情况下不断运行。这就是为什么在线程循环中经常检查终止标志并退出线程非常重要。
氮@
You should wait for the thread to terminate before you begin the process off shutting down the rest of your application, otherwise shared resources may be freed under the threads feet, possibly leading to a string of access violations. After you have waited for thread termination, then you can free it. In fact, that's what the
TThread
destructor does for you.If there are no shared resources, then sure, let it die by itself. Even if the thread terminates after the main thread, all that is required is that all your threads exit for the program to terminate. Any memory associated with the thread's object will just get cleaned up and given back to the OS with everything else.
BUT, be careful! If your thread is taking a while to exit, it can lead to a zombie process sitting there churning away without a GUI. That is why it is very important to check the
Terminated
flag very often in the thread loop, and exit the thread.N@
您的问题并不愚蠢或简单 - 请阅读 MSDN 文章。总而言之,如果您想安全起见,最好在退出应用程序之前等待后台线程终止。
Your question is not silly or simple - read the MSDN article. All in all, if you want to be on the safe side you are better to wait a background thread to terminate before exiting an application.
该线程最终将终止,Windows 将清理剩余的内存。然而,您也可以等待线程终止,因为这正是 Windows 所做的事情。您的应用程序可能似乎已关闭,因为所有窗口可能已关闭/隐藏,但应用程序进程在所有线程完成之前不会终止...
The thread will eventually terminate and Windows will clean up any memory left over. However, you might as well just wait for the thread to terminate, because that is exactly what Windows will do anyway. Your application may appear to have shut down because all windows may have been closed/hidden, but the application process won't terminate until all threads have finished...
当进程终止时,操作系统将回收所有分配的内存并关闭所有打开的句柄。您无需担心在关闭应用程序的特殊事件中内存泄漏。操作系统还将关闭所有打开的句柄**),至少在理论上是这样。考虑到所有这些,您可以安全地简单地终止线程(使用 TerminateThread(MyThread.Handle)) 从表单析构函数中,然后再杀死其他共享资源。问自己这些问题:
如果您对两者都安全,则可以使用 TerminateThread 而不是等待线程自然终止。更安全的方法可能是组合方法,也许您应该给线程一个自然终止的机会,如果它没有在 5 秒内终止,则强制终止它。
*)我说的是内存,您只能证明进程终止时的泄漏,例如您杀死的线程而不给它们正确关闭的机会,或者您不释放的全局单例类。所有其他未计算的内存都需要追踪并修复,因为它是一个错误。
**) 不幸的是,Windows 操作系统并非没有错误。示例:任何在 Windows 平台上使用过串行设备的人都知道让串行设备处于“锁定”状态是多么容易,需要重新启动才能使其再次工作。从技术上讲,这也是一个句柄,结束处理锁定它的应用程序应该解锁它。
When a process terminates the OS will reclaim all allocated memory and will close all open handles. You don't need to worry about MEMORY*) that leaks in the very special event of shutting down the application. The OS will also close all your open handles**), at least theoretically. All those taken into account, it might be safe for you to simply terminate your thread (using TerminateThread(MyThread.Handle)) from your forms destructor, before killing other shared resources. Ask yourself those questions:
If you're on the safe side with both, you can use TerminateThread and not wait for the thread to naturally terminate. A safer approach might a combined approach, maybe you should give the thread a chance to naturally terminate and, if it didn't terminate withing 5 seconds, force-terminate it.
*) I'm talking about memory you can prove only leaks on process termination, like threads you kill without giving them a chance to properly shut down, or global singleton classes you don't free. All other unaccounted memory needs to be tracked down and fixed, because it's an bug.
**) Unfortunately the Windows OS is not bug-free. Example: Anyone that worked with serial devices on the Windows platform knows how easy it is to get the serial-device in a "locked" state, requiring an restart to get it working again. Technically that's also an Handle, end-processing the application that locked it should unlock it.
为什么在创建线程时不增加变量,并在销毁事件时等待线程完成,减少变量,并在应用程序终止时只执行 Application.processmessages ?
为什么你的线程不是 freeonterminate=true ?所有共享资源都可以处理到临界区。
此致,
why you dont increment a variable when creating the thread, and on the destroy event wait until thread finish, decrement the variable, and on applicationterminate just do Application.processmessages ?
why your thread isn't freeonterminate=true ? all shared resources can be handled into a critical section.
best regards,