... if (m_pCritSect) { ASSERT(m_pCritSect->OwningThread == GetCurrentThreadId()); LeaveCriticalSection(m_pCritSect); } }
从调试CRITICAL_SECTIONS(使用VS 2005,主要是在WindowsXP上)我“知道”OwningThread(winnt.h中定义的RTL_CRITICAL_SECTION结构的成员)的值是持有锁的线程的ID的值.
但是,线程ID由DWORD(无符号长整数的typedef)值表示,而此变量的类型为HANDLE(typedef表示void *),需要reinterpret_cast才能使用basetsd.h中的HandleToULong宏来使上述代码生效.
即使是MSDN docs州:
When the first thread calls the EnterCriticalSection routine,(…)
OwningThread becomes the thread ID of the caller.
那么为什么在地球上这被定义为一个手柄呢?
编辑注意:我发现a statement,其中一张海报表明HANDLE / DWORD-Id不匹配是某些Windows内部的一些已知错误.所以也许这就是这种情况:
GetCurrentThreadId returns a DWORD,which I send up to the kernel in a
message. PsLookupThreadByThreadId takes the thread Id in a HANDLE,…
…This is a known Windows API bug (“known” in that I talked to the
relevant filter manager DEV about this,as it shows up in Filter
Manager as well because of the I/O Manager API issue.) As long as you
don’t have more than a half billion or so threads and processes (they
use a single shared handle table) you’ll be fine. Maybe by the time
that’s a real issue,we’ll be running something different. [RE: ThreadId to HANDLE for 64 bit?,08 Aug 08 14:21,Tony Mason]
解决方法
winapi是记录层,本机操作系统没有记录.运行时层也没有记录,但随着时间的推移,部分内容被揭示出来.要么因为它回填了winapi中缺少的特征.或者,在这种情况下,因为解决问题真的很有用.然而,这样做的一个核心问题是,一旦宣布声明,微软就永远不会再改变它.因为这样做会破坏现有的程序,给客户带来很大的负担.
所以,ThreadOwner字段曾经真正拥有以前Windows版本中线程的句柄.注意LockSemaphore是如何误导的,它实际上是一个自动重置事件.修理它太晚了,这只猫已经不在了.