Мой EventWaitHandle говорит: "Доступ к пути запрещен", но его не
Краткое резюме с тем, что я сейчас знаю
У меня есть EventWaitHandle
, который я создал, а затем закрыл. Когда я пытаюсь воссоздать его с помощью этого ctor, "Доступ к пути... запрещен", исключение. Это исключение встречается редко, в большинстве случаев он просто воссоздает 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: Последний поток в веб-службе, чтобы открыть этот существующий дескриптор wait, COMPLETED его работу (как в завершенном соединении с клиентом)
-
12: 00: 30,234: веб-служба получает новое соединение, еще не используя дескриптор wait. Идентификатор потока для этого соединения совпадает с идентификатором потока для последнего соединения в 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
. Я, вероятно, должен был сделать то же самое для веб-службы, но я не думал, что это необходимо.
Во всяком случае, может ли кто-нибудь увидеть, что я делаю что-то конкретно неправильно? Чрезвычайно важно поставить тесные заявления в блок finally? Мне нужно вручную управлять Close()
existing_ewh
в веб-службе?
Кроме того, я знаю, что это немного сложная проблема, поэтому дайте мне знать, если вам нужна дополнительная информация, я буду внимательно следить за ней и добавлять любую необходимую информацию или объяснения.
Справочный материал
Ответы
Ответ 1
В коде, который создает дескриптор wait в службе Windows, если он не работает (как в доступе запрещен), вы можете попытаться "открыть существующий дескриптор ожидания" с помощью
EventWaitHandle.OpenExisting(
@"Global\OurCompany.OurProduct.MyClass.EventWaitHandle",
EventWaitHandleRights.Synchronize | EventWaitHandleRights.Modify);
Хотя, я не совсем уверен, будет ли поведение оставаться неизменным в тот момент.
Примечание. Я буду благодарен за отзывы. Это потенциальный ответ, поэтому я отвечаю на свой вопрос, опять же, много комментариев приветствуются!
Примечание 2: Удивительно, что применение EventWaitHandleRights.FullControl
вместо указанных выше флагов (Synchronize
+ Modify
) не работает. Вы должны использовать образец выше.
Ответ 2
MSDN говорит:
UnauthorizedAccessException - Именованное событие существует и имеет защиту контроля доступа, но у пользователя нет EventWaitHandleRights.FullControl.
и
Вызывающий имеет полный контроль над вновь созданным объектом EventWaitHandle, даже если eventSecurity отклоняет или не предоставляет некоторые права доступа для текущего пользователя.
У вашего сервиса нет прав на получение существующего события через конструктор EventWaitHandle. (EventWaitHandleRights.FullControl не указан. И ваше именованное событие существует, пока оно открыто на нем.) Вы можете открыть существующее событие, используя EventWaitHandle.OpenExisting.