Почему нет AutoResetEventSlim в BCL?
Почему нет AutoResetEventSlim
класс в BCL?
Можно ли имитировать с помощью ManualResetEventSlim
?
3 ответа
ManualResetEvent
а также ManualResetEventSlim
оба разработаны так, чтобы они оставались сигнальными после вызова. Это обычно для совсем другого сценария, чем AutoResetEvent
,
AutoResetEvent
немедленно возвращается в состояние без сигнала после использования, которое обычно используется для другого набора сценариев. Из документации AutoResetEvents:
Как правило, вы используете этот класс, когда потокам нужен эксклюзивный доступ к ресурсу.
ManualResetEvent
(а также Slim
) обычно используются, однако, для сценария, в котором:
это сообщение касается задачи, которую один поток должен выполнить, прежде чем другие потоки смогут продолжить.
поскольку AutoResetEvent
чаще всего используется в сценариях, где несколько потоков совместно используют ресурс, время ожидания обычно не будет очень коротким. ManualResetEventSlim
Однако на самом деле он предназначен только для случаев, когда заранее известно, что время ожидания очень мало. Если ваше время ожидания не будет очень коротким, то вы должны использовать ManualResetEvent
вместо. Подробности смотрите в документации по разнице между MRE и MRES.
Когда время ожидания больше (что было бы нормальным сценарием с AutoResetEvent
), "тонкая" версия на самом деле хуже, так как она возвращается к использованию дескриптора ожидания.
Я был прослушан этим фактом также. Однако кажется, что вы можете смоделировать AutoResteEvent(Slim), используя простой SemaphoreSlim со специальной конфигурацией:
SemaphoreSlim Lock = new SemaphoreSlim( 1, 1 );
Первый параметр ( http://msdn.microsoft.com/en-us/library/dd270891(v=vs.110).aspx) определяет начальное состояние семафора: 1 означает, что может войти один поток, 0 - что Семафор должен быть выпущен первым. Так a = new AutoResetEvent( true )
переводит на = new SemaphoreSlim( 1, 1 )
а также a = new AutoResetEvent( false )
переводит на = new SemaphoreSlim( 0, 1 )
соответственно.
Второй параметр определяет максимальное количество потоков, которые могут одновременно войти в семафор. Установка в 1 позволяет ему вести себя как AutoResetEvent
,
Еще одна приятная вещь о SemaphoreSlim заключается в том, что с новым шаблоном async/await в 4.5 класс получил .WaitAsync()
метод, который можно ожидать. Таким образом, в этом случае больше не нужно вручную создавать ожидающий примитив ожидания.
Надеюсь это поможет.
Цитируя Джоша Филлипса из Microsoft (оригинал здесь ):
Что касается AutoResetEventSlim... есть ли сценарий, для которого он вам нужен? По правде говоря, создание AutoResetEvent довольно сложно, а варианты использования очень ограничены, поэтому мы сосредоточили наши усилия на другом. Если у вас есть реальная потребность в нем, я бы хотел услышать это, чтобы мы могли подумать о его создании!
Чтобы расширить комментарий: вы можете просто использовать ручное событие и всегда сбрасывать его после ожидания.
Если эта небольшая задержка между ожиданием и сбросом вызывает проблемы, вероятно, где-то в любом случае есть фундаментальная проблема. Например, если есть несколько потребителей, и вы должны пропустить только одного, возможно, событие не является подходящим инструментом для работы, и вам следует подумать
SemaphoreSlim
или даже просто сырой
Monitor
.