Краткое резюме того, что я теперь знаю
У меня есть EventWaitHandle
, который я создал, а затем закрыл. Когда я пытаюсь воссоздать его с помощью этого ctor< /strong> возникает исключение "Доступ к пути... запрещен". Это исключение встречается редко, в большинстве случаев оно просто отлично воссоздает EventWaitHandle
. С ответом, опубликованным ниже (мной), я могу успешно вызвать EventWaitHandle.OpenExisting
и продолжить работу в случае, если было выбрано исключение, однако ctor для EventWaitHandle
должен был сделать это для меня, верно? Разве это не то, что параметр out , createdNew
для?
Начальный вопрос
У меня есть следующая архитектура, служба Windows и веб-служба на одном сервере. Веб-служба сообщает службе Windows, что она должна выполнить работу, открывая и устанавливая дескриптор ожидания, которого ожидает служба Windows.
Обычно все безупречно, и я могу запускать / останавливать службу Windows без каких-либо проблем. Однако иногда, когда я останавливаю веб-службу, а затем запускаю ее снова, она совершенно не может создать дескриптор ожидания, что нарушает всю архитектуру.
Мне особенно нужно выяснить, что нарушает дескриптор ожидания события, и остановить его. Когда дескриптор ожидания «ломается», мне приходится перезагружать окна, прежде чем он снова заработает правильно, и это, очевидно, не идеально.
ОБНОВЛЕНИЕ: выдано исключение и журнал проблем
Я перезагрузил службу Windows, пока веб-служба работала, в надежде вызвать проблему, и это произошло! Некоторые имена классов были подвергнуты цензуре для корпоративной анонимности.
12:00:41,250 [7] - Stopping execution due to a ThreadAbortException
System.Threading.ThreadAbortException: Thread was being aborted.
at System.Threading.Thread.SleepInternal(Int32 millisecondsTimeout)
at OurCompany.OurProduct.MyClass.MyClassCore.MonitorRequests()
12:00:41,328 [7] - Closing Event Wait Handle
12:00:41,328 [7] - Finally block reached
12:00:42,781 [6] - Application Start
12:00:43,031 [6] - Creating EventWaitHandle: Global\OurCompany.OurProduct.MyClass.EventWaitHandle
12:00:43,031 [6] - Creating EventWaitHandle with the security entity name of : Everyone
12:00:43,078 [6] - Unhandled Exception
System.UnauthorizedAccessException: Access to the path 'Global\OurCompany.OurProduct.MyClass.EventWaitHandle' is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.Threading.EventWaitHandle..ctor(Boolean initialState, EventResetMode mode, String name, Boolean& createdNew, EventWaitHandleSecurity eventSecurity)
at OurCompany.OurProduct.MyClassLibrary.EventWaitHandleFactory.GetNewWaitHandle(String handleName, String securityEntityName, Boolean& created)
at OurCompany.OurProduct.MyClassLibrary.EventWaitHandleFactory.GetNewEventWaitHandle()
at OurCompany.OurProduct.MyClass.MyClassCore..ctor()
Приблизительный график:
11:53:09,937: Последний поток в веб-службе, открывающий существующий дескриптор ожидания, ЗАВЕРШИЛ свою работу (как при разрыве соединения с клиентом).
12:00:30,234: веб-служба получает новое соединение, еще не используя дескриптор ожидания. Идентификатор потока для этого соединения совпадает с идентификатором потока для последнего соединения в 11:53.
12:00:41,250: служба Windows останавливается
12:00:42,781: Служба Windows запускается
12:00:43,078: служба Windows завершила сбой.
12:00:50,234: веб-служба фактически смогла открыть вызов Set() дескриптора ожидания без каких-либо исключений и т. д.
12:02:00,000: я попытался перезагрузить службу Windows, то же самое исключение
12:36:57,328: После произвольного ожидания 36 минут я смог запустить службу Windows без полной перезагрузки системы.
Код службы Windows
Инициализация:
// I ran into security issues so I open the global EWH
// and grant access to Everyone
var ewhSecurity = new EventWaitHandleSecurity();
ewhSecurity.AddAccessRule(
new EventWaitHandleAccessRule(
"Everyone",
EventWaitHandleRights.Synchronize | EventWaitHandleRights.Modify,
AccessControlType.Allow));
this.ewh = new EventWaitHandle(
false,
EventResetMode.AutoReset,
@"Global\OurCompany.OurProduct.MyClass.EventWaitHandle",
out created,
ewhSecurity);
// the variable "created" is logged
Использование:
// wait until the web service tells us to loop again
this.ewh.WaitOne();
Утилизация/закрытие:
try
{
while (true)
{
// entire service logic here
}
}
catch (Exception e)
{
// should this be in a finally, instead?
if (this.ewh != null)
{
this.ewh.Close();
}
}
Код веб-службы
Инициализация:
// NOTE: the wait handle is a member variable on the web service
this.existing_ewh = EventWaitHandle.OpenExisting(
@"Global\OurCompany.OurProduct.MyClass.EventWaitHandle");
Использование:
// wake up the windows service
this.existing_ewh.Set();
Поскольку EventWaitHandle
является переменной-членом веб-службы, у меня нет кода, специально закрывающего ее. Фактически, единственный код, который взаимодействует с EventWaitHandle
в веб-сервисе, размещен выше.
Оглядываясь назад, я, вероятно, должен был поместить Close()
из блока catch
в блок finally
. Я, вероятно, должен был сделать то же самое для веб-сервиса, но я не думал, что это нужно.
В любом случае, может ли кто-нибудь увидеть, делаю ли я что-то конкретно неправильно? Критически важно помещать операторы close в блок finally? Нужно ли мне вручную управлять Close()
из existing_ewh
в веб-службе?
Кроме того, я знаю, что это довольно сложная проблема, поэтому дайте мне знать, если вам нужна дополнительная информация, я буду внимательно следить за ней и добавлю любую необходимую информацию или пояснения.
Справочный материал