System.Threading.Monitor.Wait 方法
本文提供了此 API 参考文档的补充说明。
Wait(Object, Int32, Boolean) 方法
此方法在重新获取参数的 obj
排他锁之前不会返回。
当前拥有指定对象的锁的线程调用此方法,以便释放该对象,以便另一个线程可以访问它。 调用方在等待重新获取锁时被阻止。 当调用方需要等待由于另一个线程的操作而发生的状态更改时,将调用此方法。
超时可确保如果另一个线程在不首先调用 Pulse 或 PulseAll 方法的情况下释放锁,则当前线程不会无限期阻止。 它还会将线程移到就绪队列,在等待队列中绕过其他线程,以便可以更快地重新获取锁。 线程可以测试方法的 Wait 返回值,以确定它在超时之前是否重新获取锁。线程可以评估导致它进入等待的条件,并在必要时再次调用 Wait 该方法。
当线程调用 Wait
时,它会释放锁并进入等待队列。 此时,允许就绪队列中的下一个线程(如果有)控制锁。 调用 Wait
的线程将保留在等待队列中,直到持有锁的线程调用 PulseAll,或者它是队列中的下一个线程,还有一个持有锁的线程调用 Pulse。 但是,如果在 millisecondsTimeout
另一个线程调用此对象的 Pulse 或 PulseAll 方法之前经过,则原始线程将移动到就绪队列,以便重新获得锁定。
注意
如果 Infinite 为 millisecondsTimeout
参数指定,则此方法无限期地阻止,除非锁调用 Pulse 的持有者或 PulseAll。 如果 millisecondsTimeout
等于 0,则调用 Wait
释放锁的线程,然后立即进入就绪队列以重新获得锁。
调用方执行 Wait
一次,而不考虑为指定对象调用的次数 Enter 。 从概念上讲, Wait
该方法存储调用方在对象上调用 Enter 的次数,并根据需要多次调用 Exit 以完全释放锁定的对象。 然后,调用方在等待重新获取对象时阻止。 当调用方重新获取锁时,系统会根据需要多次调用 Enter 来还原调用方保存 Enter 的计数。 仅调用 Wait
释放指定对象的锁;如果调用方是其他对象的锁的所有者,则不会释放这些锁。
注意
同步对象包含多个引用,包括对当前保存锁的线程的引用、对就绪队列的引用、包含准备获取锁的线程,以及对等待队列的引用,其中包含等待通知对象状态更改的线程。
Pulse必须在同步的代码块内调用该方法PulseAll和Wait
方法。
该方法的注释 Pulse 说明了当 Pulse 没有线程正在等待时调用会发生什么情况。
Wait(Object, TimeSpan, Boolean) 方法
此方法在重新获取参数的 obj
排他锁之前不会返回。
当前拥有指定对象的锁的线程调用此方法,以便释放该对象,以便另一个线程可以访问它。 调用方在等待重新获取锁时被阻止。 当调用方需要等待由于另一个线程的操作而发生的状态更改时,将调用此方法。
超时可确保如果另一个线程在不首先调用 Pulse 或 PulseAll 方法的情况下释放锁,则当前线程不会无限期阻止。 它还会将线程移到就绪队列,在等待队列中绕过其他线程,以便可以更快地重新获取锁。 线程可以测试方法的 Wait 返回值,以确定它在超时之前是否重新获取锁。线程可以评估导致它进入等待的条件,并在必要时再次调用 Wait 该方法。
当线程调用 Wait
时,它会释放锁并进入等待队列。 此时,允许就绪队列中的下一个线程(如果有)控制锁。 调用 Wait
的线程将保留在等待队列中,直到持有锁的线程调用 PulseAll,或者它是队列中的下一个线程,还有一个持有锁的线程调用 Pulse。 但是,如果在 timeout
另一个线程调用此对象的 Pulse 或 PulseAll 方法之前经过毫秒,则原始线程将移动到就绪队列,以便重新获得锁定。
注意
TimeSpan如果为timeout
参数指定了表示的 -1 毫秒,此方法将无限期地阻止,除非锁调用Pulse的持有者或 PulseAll。 如果 timeout
为 0 毫秒,则调用 Wait
的线程会释放锁,然后立即进入就绪队列以重新获得锁。
调用方执行 Wait
一次,而不考虑为指定对象调用的次数 Enter 。 从概念上讲, Wait
该方法存储调用方在对象上调用 Enter 的次数,并根据需要多次调用 Exit 以完全释放锁定的对象。 然后,调用方在等待重新获取对象时阻止。 当调用方重新获取锁时,系统会根据需要多次调用 Enter 来还原调用方保存 Enter 的计数。 仅调用 Wait
释放指定对象的锁;如果调用方是其他对象的锁的所有者,则不会释放这些锁。
注意
同步对象包含多个引用,包括对当前保存锁的线程的引用、对就绪队列的引用、包含准备获取锁的线程,以及对等待队列的引用,其中包含等待通知对象状态更改的线程。
Pulse必须在同步的代码块内调用该方法PulseAll和Wait
方法。
该方法的注释 Pulse 说明了当 Pulse 没有线程正在等待时调用会发生什么情况。
退出上下文
除非从非默认托管上下文内部调用该方法,否则Wait参数exitContext
不起作用。 如果线程在对派生自 ContextBoundObject的类实例的调用中,则可能会发生这种情况。 即使当前在未派生自 ContextBoundObject的类上执行方法,例如 String,如果在当前应用程序域中的堆栈上存在, ContextBoundObject 也可以位于非默认上下文中。
当代码在非默认上下文中执行时,指定 true
它 exitContext
会导致线程在执行 Wait 该方法之前退出非默认托管上下文(即转换到默认上下文)。 调用方法完成后 Wait ,它将返回到原始非默认上下文。
当上下文绑定类 SynchronizationAttribute 应用属性时,这非常有用。 在这种情况下,对类成员的所有调用都会自动同步,并且同步域是该类的整个代码正文。 如果成员调用堆栈中的代码调用Wait该方法并指定true
exitContext
,则线程将退出同步域,从而允许在调用对象的任何成员时被阻止的线程继续。 Wait此方法返回时,发出调用的线程必须等待重新输入同步域。