Поделиться через


Методы 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 столько раз, сколько необходимо для восстановления сохраненного счётчика для вызывающего. Вызов 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 столько раз, сколько необходимо для восстановления сохраненного счётчика для вызывающего. Вызов Wait освобождает блокировку только для указанного объекта. Если вызывающий объект является владельцем блокировок на других объектах, эти блокировки не освобождаются.

Замечание

Синхронизированный объект содержит несколько ссылок, включая ссылку на поток, содержащий блокировку, ссылку на готовую очередь, содержащую потоки, готовые к получению блокировки, и ссылку на очередь ожидания, которая содержит потоки, ожидающие уведомления об изменении состояния объекта.

Методы Pulse, PulseAll и Wait должны вызываться из синхронизированного блока кода.

Примечания к методу Pulse объясняют, что происходит, если Pulse вызывается в то время, когда нет ожидающих потоков.

Выйти из контекста

Параметр exitContext не действует, если метод Wait вызывается изнутри непо умолчанию управляемого контекста. Это может произойти, если ваш поток находится внутри вызова экземпляра класса, производного от ContextBoundObject. Даже если в настоящее время вы выполняете метод в классе, который не является производным от ContextBoundObject, как, например, String, вы можете находиться в контексте не по умолчанию, если ContextBoundObject находится в вашем стеке в текущем домене приложения.

При выполнении кода в контексте, отличном от контекста по умолчанию, указание true для exitContext вызывает выход потока из альтернативного управляемого контекста (то есть переход в контекст по умолчанию) перед выполнением метода Wait. Он возвращается в исходный недефаулный контекст после завершения вызова Wait метода.

Это может быть полезно, когда к классу с привязкой к контексту применяется атрибут SynchronizationAttribute. В этом случае все вызовы к членам класса синхронизируются автоматически, а домен синхронизации — весь текст кода для класса. Если код в стеке вызовов члена вызывает Wait метод и указывает true для exitContextэтого, поток выходит из домена синхронизации, что позволяет потоку, блокированному при вызове любого члена объекта, продолжить. Когда метод Wait возвращается, поток, который сделал вызов, должен ждать повторного вхождения в домен синхронизации.