Книга Албахари удивительна, вы должны действительно прочитать ее некоторое время.В последнее время его очень много!
То, что вы хотите
Вы хотите EventWaitHandle
(EWH), они хороши, потому что нечего обойти, они используютсядля сигнальных потоков (либо в том же, либо в другом процессе) и, как следует из названия, их можно ожидать.
Как вы используете это
Вы бы открыли один в потоке, которыйвыполняет ожидание, вы открываете его с заданным именем, о котором другой поток узнает.Затем вы ждете этот дескриптор ожидания.
Поток сигнализации откроет существующий дескриптор ожидания с тем же именем (имя является строкой) и вызовет set
для него.
Различия
AutoResetEvent
с и ManualResetEvent
с оба наследуются от EWH и на самом деле они просто EWH, они просто действуют по-разному.Какой из них вам нужен, зависит только от того, хотите ли вы, чтобы EWH выступал в качестве ворот или турникета. Вас волнует это только в том случае, если вы используете дескриптор ожидания более одного раза или вы ожидаете в этом дескрипторе ожидания более одного потока. Я использовал ожидание, обрабатывает приличное количество (полагаю), и яне думайте, что я когда-либо использовал Руководство.
Важно знать
Что бы вы ни делали, не передавайте экземпляр дескриптора ожидания, они предназначеныбыть открытыми отдельно своими потоками.Указанное вами имя будет гарантировать, что они будут «одинаковыми» дескрипторами ожидания.
Если потоки находятся в разных процессах, то вам нужно будет добавить префикс имени EWH к @"Global\"
, иначе имена дескрипторов ожидания будут заключены в один и тот же процесс.В качестве альтернативы, если вы используете их все в одном и том же процессе, не используйте глобальное пространство имен.Когда вы не указываете префикс с обратной косой чертой, он автоматически добавляется, чтобы сохранить его в тайне, но вам не нужно знать этот префикс.
Имейте в виду, что EWH можетполучить разрешение, и если у вас возникнут проблемы с этим, я рекомендую вам использовать EventWaitHandleRights.FullControl
, но вы можете просмотреть полное перечисление EventWaitHandleRights здесь .
Мне нравитсяназвать мои EWH с Guid.NewGuid().ToString("N")
( Guid.NewGuid & Guid.ToString ).Обычно я делаю это при создании потока сигнализации, поскольку вы можете легко передать ему информацию в это время.Таким образом, в этом случае начальный поток создает строку и передает ее сигнальному потоку при его создании.Таким образом, оба потока знают имя без необходимости какой-либо сложной передачи переменных между потоками.
EWH реализует IDisposable
, поэтому оберните его вusing
блок
Условия гонки
EWH хороши, потому что если по какой-либо причине поток сигнализации открывается и сигнализирует дескриптор ожидания перед ожиданиемпоток даже создает его, все будет работать, и ожидающий поток будет оповещен, как только он достигнет ожидания.
Из-за этого, тем не менее, поток, ожидающий его, должен будет иметь некоторую ловушку ошибок, потому что вам нужно будет вызвать OpenExisting
.Если вы позвоните по одному из ctor
и EWH уже открыт, вы получите UnauthorizedAccessException
или WaitHandleCannotBeOpenedException
, как описано здесь, в разделе Исключения ,Вы по-прежнему сможете открывать этот EWH и получать необходимую вам функциональность. Возможно, вам просто придется открыть его, а не создавать.