System.Threading.Monitor.Wait 方法

本文提供了此 API 参考文档的补充说明。

Wait(Object, Int32, Boolean) 方法

此方法在重新获取参数的 obj 排他锁之前不会返回。

当前拥有指定对象的锁的线程调用此方法,以便释放该对象,以便另一个线程可以访问它。 调用方在等待重新获取锁时被阻止。 当调用方需要等待由于另一个线程的操作而发生的状态更改时,将调用此方法。

超时可确保如果另一个线程在不首先调用 PulsePulseAll 方法的情况下释放锁,则当前线程不会无限期阻止。 它还会将线程移到就绪队列,在等待队列中绕过其他线程,以便可以更快地重新获取锁。 线程可以测试方法的 Wait 返回值,以确定它在超时之前是否重新获取锁。线程可以评估导致它进入等待的条件,并在必要时再次调用 Wait 该方法。

当线程调用 Wait时,它会释放锁并进入等待队列。 此时,允许就绪队列中的下一个线程(如果有)控制锁。 调用 Wait 的线程将保留在等待队列中,直到持有锁的线程调用 PulseAll,或者它是队列中的下一个线程,还有一个持有锁的线程调用 Pulse。 但是,如果在 millisecondsTimeout 另一个线程调用此对象的 PulsePulseAll 方法之前经过,则原始线程将移动到就绪队列,以便重新获得锁定。

注意

如果 InfinitemillisecondsTimeout 参数指定,则此方法无限期地阻止,除非锁调用 Pulse 的持有者或 PulseAll。 如果 millisecondsTimeout 等于 0,则调用 Wait 释放锁的线程,然后立即进入就绪队列以重新获得锁。

调用方执行 Wait 一次,而不考虑为指定对象调用的次数 Enter 。 从概念上讲, Wait 该方法存储调用方在对象上调用 Enter 的次数,并根据需要多次调用 Exit 以完全释放锁定的对象。 然后,调用方在等待重新获取对象时阻止。 当调用方重新获取锁时,系统会根据需要多次调用 Enter 来还原调用方保存 Enter 的计数。 仅调用 Wait 释放指定对象的锁;如果调用方是其他对象的锁的所有者,则不会释放这些锁。

注意

同步对象包含多个引用,包括对当前保存锁的线程的引用、对就绪队列的引用、包含准备获取锁的线程,以及对等待队列的引用,其中包含等待通知对象状态更改的线程。

Pulse必须在同步的代码块内调用该方法PulseAllWait方法。

该方法的注释 Pulse 说明了当 Pulse 没有线程正在等待时调用会发生什么情况。

Wait(Object, TimeSpan, Boolean) 方法

此方法在重新获取参数的 obj 排他锁之前不会返回。

当前拥有指定对象的锁的线程调用此方法,以便释放该对象,以便另一个线程可以访问它。 调用方在等待重新获取锁时被阻止。 当调用方需要等待由于另一个线程的操作而发生的状态更改时,将调用此方法。

超时可确保如果另一个线程在不首先调用 PulsePulseAll 方法的情况下释放锁,则当前线程不会无限期阻止。 它还会将线程移到就绪队列,在等待队列中绕过其他线程,以便可以更快地重新获取锁。 线程可以测试方法的 Wait 返回值,以确定它在超时之前是否重新获取锁。线程可以评估导致它进入等待的条件,并在必要时再次调用 Wait 该方法。

当线程调用 Wait时,它会释放锁并进入等待队列。 此时,允许就绪队列中的下一个线程(如果有)控制锁。 调用 Wait 的线程将保留在等待队列中,直到持有锁的线程调用 PulseAll,或者它是队列中的下一个线程,还有一个持有锁的线程调用 Pulse。 但是,如果在 timeout 另一个线程调用此对象的 PulsePulseAll 方法之前经过毫秒,则原始线程将移动到就绪队列,以便重新获得锁定。

注意

TimeSpan如果为timeout参数指定了表示的 -1 毫秒,此方法将无限期地阻止,除非锁调用Pulse的持有者或 PulseAll。 如果 timeout 为 0 毫秒,则调用 Wait 的线程会释放锁,然后立即进入就绪队列以重新获得锁。

调用方执行 Wait 一次,而不考虑为指定对象调用的次数 Enter 。 从概念上讲, Wait 该方法存储调用方在对象上调用 Enter 的次数,并根据需要多次调用 Exit 以完全释放锁定的对象。 然后,调用方在等待重新获取对象时阻止。 当调用方重新获取锁时,系统会根据需要多次调用 Enter 来还原调用方保存 Enter 的计数。 仅调用 Wait 释放指定对象的锁;如果调用方是其他对象的锁的所有者,则不会释放这些锁。

注意

同步对象包含多个引用,包括对当前保存锁的线程的引用、对就绪队列的引用、包含准备获取锁的线程,以及对等待队列的引用,其中包含等待通知对象状态更改的线程。

Pulse必须在同步的代码块内调用该方法PulseAllWait方法。

该方法的注释 Pulse 说明了当 Pulse 没有线程正在等待时调用会发生什么情况。

退出上下文

除非从非默认托管上下文内部调用该方法,否则Wait参数exitContext不起作用。 如果线程在对派生自 ContextBoundObject的类实例的调用中,则可能会发生这种情况。 即使当前在未派生自 ContextBoundObject的类上执行方法,例如 String,如果在当前应用程序域中的堆栈上存在, ContextBoundObject 也可以位于非默认上下文中。

当代码在非默认上下文中执行时,指定 trueexitContext 会导致线程在执行 Wait 该方法之前退出非默认托管上下文(即转换到默认上下文)。 调用方法完成后 Wait ,它将返回到原始非默认上下文。

当上下文绑定类 SynchronizationAttribute 应用属性时,这非常有用。 在这种情况下,对类成员的所有调用都会自动同步,并且同步域是该类的整个代码正文。 如果成员调用堆栈中的代码调用Wait该方法并指定trueexitContext,则线程将退出同步域,从而允许在调用对象的任何成员时被阻止的线程继续。 Wait此方法返回时,发出调用的线程必须等待重新输入同步域。