Подтвердить что ты не робот

Когда я буду использовать AutoResetEvent и ManualResetEvent вместо Monitor.Wait()/Monitor.Pulse()?

Оба они, похоже, выполняют ту же самую цель. Когда я бы выбрал один за другим?

4b9b3361

Ответ 1

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

Используйте монитор, если вы хотите ограничить доступ к структуре данных, ограничив, сколько потоков может получить к нему доступ.

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

Кроме того, события могут быть названы (см. метод OpenExisting), что позволяет использовать их для синхронизации в разных процессах.

Ответ 2

На мой взгляд, лучше использовать Monitor, если вы можете, Monitor.Wait и Monitor.Pulse/PulseAll используются для сигнализации между потоками (как и Manual/AutoResetEvent), однако монитор работает быстрее и не использует собственный системный ресурс. Также очевидно, что Monitor реализован в пользовательском режиме и управляется, тогда как Manual/AutoResetEvents требует перехода в режим ядра и p/invoke на собственные вызовы win32, которые используют дескриптор ожидания.

Бывают ситуации, когда вам нужно будет использовать Manual/AutoResetEvent, например, чтобы сигнализировать между процессами, которые вы можете использовать именованными событиями, и я предполагаю, что вы указываете собственные потоки в своем приложении.

Я просто срываю то, что я прочитал в эту отличную статью о потоковом использовании.

Вся статья стоит прочитать, однако ссылка переместит вас в секцию дескриптора ожидания, которая описывает события и отслеживает ожидание/импульс.

Ответ 3

Если вы хотите, чтобы поток отправлял или получал двоичный сигнал без использования критического раздела, вы использовали бы WaitHandle. Monitor.Wait и Monitor.Pulse, с другой стороны, требуется критический раздел. Как и большинство механизмов синхронизации в BCL, существует некоторое совпадение в том, как можно использовать два упомянутых вами. Но не думайте ни на минуту, что они выполняют ту же цель.

Monitor.Wait и Monitor.Pulse являются гораздо более примитивным механизмом синхронизации, чем MRE или ARE. Фактически, вы можете построить MRE или ARE, используя не что иное, как класс Monitor. Наиболее важным понятием является то, как отличаются методы Monitor.Wait и WaitHandle.WaitOne. Wait и WaitOne будут помещать поток в состояние WaitSleepJoin, что означает, что поток становится бездействующим и реагирует только на Thread.Interrupt или соответствующий вызов Pulse или Set. Но, и это существенное различие, Wait оставит критический раздел и снова получит его в атомном режиме. WaitOne просто не может этого сделать. Это принципиально отличается от того, как ведут себя эти механизмы синхронизации, которые определяют сценарии, в которых они могут быть использованы.

В большинстве ситуаций вы выбрали MRE или ARE. Они удовлетворяют большинству ситуаций, когда один поток должен получать сигнал от другого. Однако, если вы хотите создать свой собственный механизм сигнализации, вам нужно будет использовать Wait и Pulse. Но, опять же,.NET BCL имеет большинство популярных сигнальных механизмов, которые уже были рассмотрены. Следующие сигнальные механизмы уже существуют 1.

  • ManualResetEvent (или ManualResetEventSlim)
  • AutoResetEvent
  • Семафор (или СемафорСлим)
  • EventWaitHandle
  • CountdownEvent
  • Барьер

1 Почетное упоминание относится к классу BlockingCollection. Это не сигнальные механизмы как таковые, но у него есть качества сигнального механизма с дополнительным преимуществом, которое вы можете присоединить к сигналу. В этом случае сигнал означает, что элемент доступен в коллекции, а данные, связанные с этим сигналом, являются самим элементом.