线程退出时的清理
当我的线程退出时,需要关闭其句柄并将其重置为 NULL。不是在线程关闭事件(例如 ::WaitForSingleObject( s_hMyThread, TIMEOUT );
)上执行此操作,而是关闭句柄并将其重置为线程中的最后一件事是否有效,在它回来之前,像这样吗?
DWORD MyThread( LPVOID pParam )
{
// Does something...
::CloseHandle( s_hMyThread );
s_hMyThread = NULL;
return 0;
}
When my thread exits its handle needs to be closed and reset to NULL. Rather than doing this upon the thread-closure event (e.g. ::WaitForSingleObject( s_hMyThread, TIMEOUT );
), would it be valid to close the handle and reset it as the very last thing in the thread, before it returns, like this?
DWORD MyThread( LPVOID pParam )
{
// Does something...
::CloseHandle( s_hMyThread );
s_hMyThread = NULL;
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你可以做到的。
关闭线程句柄不会终止关联的线程或删除线程对象。线程对象保留在系统中,直到线程终止并且它的所有句柄都已通过调用 CloseHandle 关闭。
但是,如果您这样做,您将无法从应用程序的主线程检查该线程是否仍在运行,因此您将无法安全退出应用程序。还有一件事:如果您的线程以意外方式终止,您将不会释放句柄。
You can do it.
Closing a thread handle does not terminate the associated thread or remove the thread object. The thread object remains in the system until the thread has terminated and all handles to it have been closed through a call to CloseHandle.
However, if you'll do it, you'll lose to ability to check from the main thread of your application if the thread is still running, therefore, you won't be able to safely exit your application. One more thing: if your thread terminates in an unexpected way, you won't release the handle.
我不清楚这是否会使线程对象处于任何等待它的人都可以确定发生了什么的状态。根据文档:
我怀疑您会得到一个从 CreateThread 返回的线程句柄,但让创建的线程关闭该句柄。似乎违背了 API 设计的初衷,不是吗?不管它是否有效,我都不会这样做,除非它对你的设计至关重要。
It's not clear to me that this will leave the thread object in a state where anybody waiting on it can determine what's going on. Per the docs:
It's suspect to me that you would get a thread handle returned from CreateThread, but have the created thread close that handle. Seems counter to the intent of the API design, no? Regardless of whether it works, I would not do this unless it's essential to your design.
从技术上讲,它是有效的。您可以像关闭任何其他句柄一样关闭该句柄 - 在您喜欢的任何线程中。
但是像您在示例中所做的那样关闭线程的句柄并不是一个好主意 - 它通常毫无意义,而且可能不安全,因为访问 s_hMyThread 变量时没有正确的同步。当然,您可以对
s_hMyThread
变量进行适当的同步,但这将是太多难以支持的代码,实际上没有真正的目的。从这个线程关闭线程句柄是没有意义的,因为保持线程句柄打开的唯一原因是在某个地方等待该线程完成,这自然意味着当线程完成时该句柄应该仍然打开。通常好的做法是(1)如果您不必等到线程完成,则在创建后的下一行关闭其句柄(CreateThread 之后的下一次调用),(2)如果您必须等待该线程完成,则关闭当您知道线程的对象已发出信号(即线程已完成)时,线程的句柄。当您确实需要线程句柄时,我看不到其他用法。
Technically it is valid. You can close that handle just like any other handle - in any thread you like.
But closing thread's handle like you did in your example is not very good idea - it is generally pointless and it may be unsafe because there is no proper synchronization when accessing s_hMyThread variable. Of course you might do proper synchronization of your
s_hMyThread
variable but it would be too much hard-to-support code with no real purpose actually. There is no purpose in closing thread's handle from this very thread because the only reason of keeping thread's handle open is waiting somewhere this thread to complete that naturally implies that the handle should still be open when the thread completes.Usually good practice is (1) if you don't have to wait until thread completes then you close its handle next line after its creation (next call after CreateThread), (2) if you do have to wait this thread's completion then you close thread's handle when you know thread's object is signalled (i.e. thread completed). I see no other usages when you really need thread's handle.
在阅读了您对 Lior Kogan 的回答的评论后(“所讨论的线程被设计为单次执行,以处理一些可能会锁定应用程序的内容,因此一旦完成,就完成了。”),在我看来你对那个手柄根本不感兴趣。
那么为什么不
CloseHandle(CreateThread(...));
呢?这是完全允许的。或者更好的是,使用
_beginthread
和_endthread
。即使您确实对该线程有兴趣并且例如想要等待它完成,这也会起作用。来自文档:“_endthread 自动关闭线程句柄(而 _endthreadex 不会)。因此,在使用 _beginthread 和 _endthread 时,不要通过调用 Win32 CloseHandle API 显式关闭线程句柄。”
无需担心关闭任何内容,而且它还有一个额外的好处,即不会因损坏的 CRT 实现而泄漏。
After reading your comment to Lior Kogan's answer ("The thread in question is designed as a single-shot to handle some stuff that would otherwise lock up the application, so once it's done it's done."), it appears to me that you are not interested in that handle at all.
Why do you not
CloseHandle(CreateThread(...));
then? This is perfectly allowed.Or better yet, use
_beginthread
and_endthread
. That will work even if you do have some interest in that thread and for example want to wait for it to finish.From the docs: "_endthread automatically closes the thread handle (whereas _endthreadex does not). Therefore, when using _beginthread and _endthread, do not explicitly close the thread handle by calling the Win32 CloseHandle API."
No need to worry about closing anything, and it has the additional benefit of not leaking with broken CRT implementations.