要忠实地看看有没有实现Monitor.Wait
一个更简单的方法,我们会ahve探讨如何功能处于较低水平。实际的实现最终是用C语言编写的,对我们来说是隐藏的,但是对于Monitor.Wait(object)
,我们可以用以下方式来追踪调用链;
Monitor.Wait(o)
-- return Monitor.Wait(o, -1, false)
Monitor.Wait(o, -1, false)
-- Monitor.ObjWait(false [exitContext], -1 [millisecondsTimeout], o)
从这里很难看出即使在ILSpy中发生了什么。根据Tigran与Monitor
对象源的链接,我们在源代码中留下以下内容:
/*========================================================================
** Waits for notification from the object (via a Pulse/PulseAll).
** timeout indicates how long to wait before the method returns.
** This method acquires the monitor waithandle for the object
** If this thread holds the monitor lock for the object, it releases it.
** On exit from the method, it obtains the monitor lock back.
** If exitContext is true then the synchronization domain for the context
** (if in a synchronized context) is exited before the wait and reacquired
**
** Exceptions: ArgumentNullException if object is null.
========================================================================*/
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool ObjWait(bool exitContext, int millisecondsTimeout, Object obj)
该描述是相当自我解释的,它是干什么的,以什么顺序。然而,它的确切实现是从包含关键代码的各种方法中打包出来的。
extern
specifies实际执行在于另一个程序集。当访问非托管代码(这里不是这种情况)或可能是extern alias时,它可以与DllImport
一起使用。从这里按照SO post asking about where to find the implementation of extern methods,你必须看看C代码本身,它可以在Core CLR(信誉Scott Chamberlain)中找到。
从这里我们看看在CLR中的ObjWait()
的C方法实现,其中maps(第1027行)到ObjectNative::WaitTimeout
;
FCIMPL3(FC_BOOL_RET, ObjectNative::WaitTimeout, CLR_BOOL exitContext, INT32 Timeout, Object* pThisUNSAFE)
{
FCALL_CONTRACT;
BOOL retVal = FALSE;
OBJECTREF pThis = (OBJECTREF) pThisUNSAFE;
HELPER_METHOD_FRAME_BEGIN_RET_1(pThis);
if (pThis == NULL)
COMPlusThrow(kNullReferenceException, W("NullReference_This"));
if ((Timeout < 0) && (Timeout != INFINITE_TIMEOUT))
COMPlusThrowArgumentOutOfRange(W("millisecondsTimeout"), W("ArgumentOutOfRange_NeedNonNegNum"));
retVal = pThis->Wait(Timeout, exitContext);
HELPER_METHOD_FRAME_END();
FC_RETURN_BOOL(retVal);
}
FCIMPLEND
之前进入这个,这是值得看的this(也归功于斯科特·张伯伦),其中规定;
FCalls在托管代码中标识为外部方法,并设置了MethodImplOptions.InternalCall位。
这解释了我们与ObjWait()
和ObjectNative::WaitTimeout
的链接。因此,进一步分解这个问题,我们可以看到基本的null
和参数检查,如果有的话会引发适当的异常。关键是要拨打电话pThis->Wait()
......在这一点上,我无法进一步追踪......。
从这里我们得到Object::Wait
(line 531),然后去SyncBlock::Wait
(line 3442)。在这一点上,我们拥有大部分实施的内容,并且有相当多的内容。
鉴于上述所有,并又回到了你的要求再简单的实现,我会警惕简化Monitor.Wait()
的。有一个很多正在引擎盖下,它会很容易犯一个错误,并在其他实现中有潜在的错误。
编辑
严重喊出Scott Chamberlain谁做的最下方ILSpy级和钻研的调查/调试C代码堆栈。几乎所有ILSpy级以下的调查工作都是他的,我只是把它编译成一个答案。
[System.Threading.Monitor](http://referencesource.microsoft.com/#mscorlib/system/threading/monitor.cs) – Tigran
链接到您的问题的文章有效地回答它,据我所知。你在寻找什么额外的信息? – DiskJunky
作为更好地理解等待函数的一种方式,我很好奇它是否可以使用已发布的.Net API作为简单函数重新实现它。它更容易理解为只是代码...... –