本文提供了此 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参数指定了一个表示 -1 毫秒的timeout
,此方法将无期限地阻塞,除非锁的持有者调用Pulse或PulseAll。 如果 timeout
为 0 毫秒,则调用 Wait
的线程会释放锁,然后立即进入就绪队列以重新获得锁。
调用方仅执行一次 Wait
,无论为指定对象调用 Enter 的次数是多少。 从概念上讲, Wait
该方法存储调用方在对象上调用 Enter 的次数,并根据需要多次调用 Exit 以完全释放锁定的对象。 然后,调用方在等待重新获取对象时阻止。 当调用方重新获取锁时,系统会根据需要多次调用 Enter 来还原调用方保存 Enter 的计数。 仅调用 Wait
释放指定对象的锁;如果调用方是其他对象的锁的所有者,则不会释放这些锁。
注释
同步对象包含多个引用,包括对当前保存锁的线程的引用、对就绪队列的引用、包含准备获取锁的线程,以及对等待队列的引用,其中包含等待通知对象状态更改的线程。
必须在同步的代码块内调用Pulse、PulseAll和Wait
方法。
对于 Pulse 方法的注释解释了如果在没有线程等待时调用 Pulse 会发生什么。
退出上下文
只有从非默认托管上下文内部调用 exitContext
方法时,Wait 参数才会生效。 如果线程是在对派生自 ContextBoundObject 的类实例进行调用时,这种情况可能会发生。 即使当前在一个未派生自 ContextBoundObject 的类上执行方法(例如 String),如果在当前应用程序域的堆栈上存在 ContextBoundObject,那么它可能位于非默认上下文中。
当代码在非默认上下文中执行时,为 true
指定 exitContext
会导致线程在执行 Wait 方法之前,退出非默认托管上下文并转换到默认上下文。 在对 Wait 方法的调用完成后,它将返回到原始的非默认上下文。
当上下文绑定的类应用 SynchronizationAttribute 属性时,这可能非常有用。 在这种情况下,对类成员的所有调用都会自动同步,并且同步域是该类的整个代码正文。 如果某个成员的调用堆栈中的代码调用Wait方法,并为true
指定exitContext
,则线程将退出同步域,从而允许被阻止在调用该对象任何成员时的线程继续执行。 Wait此方法返回时,发出调用的线程必须等待重新输入同步域。