Как узнать, был ли вызван EventWaitHandle.Set
Есть ли способ узнать, какой EventWaitHandle
был вызван.
У меня есть два пользовательских класса с 2 различными именами событий всей системы.
Причина, по которой они у меня были, состоит в том, чтобы различать, какую функцию активировать
Проблема, с которой я столкнулся сейчас, заключается в том, как определить, какое событие было инициировано?
EventWaitHandle _ew1 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode1");
EventWaitHandle _ew2 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode2");
Так что если _ew1.Set()
вызывается, то мне нужно выполнить Process1
,
Если вызывается _ew2.Set(), мне нужно выполнить Process2
,
Обновление: добавлено больше информации.
Основным потоком является служба Windows. который сигнализируется веб-приложением и настольным приложением. поэтому в основном сервису необходимо определить, кто вызвал событие, либо из веб-приложения, либо из приложения для настольного компьютера, если это веб-приложение, а затем выполнить SP1, если это приложение Windows, а затем выполнить SP2.
5 ответов
Идея 1
Статический метод WaitHandle.WaitAny возвращает индекс сигнального дескриптора ожидания, поэтому простейшим решением будет проверка этого индекса.
пример
static class Program
{
private static Random _random = new Random();
private static AutoResetEvent[] _eventHandles = new[] {new AutoResetEvent(false), new AutoResetEvent(false)};
static void Main()
{
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(Method);
threads[i].Start();
var handleIndex = WaitHandle.WaitAny(_eventHandles);
Console.WriteLine(handleIndex == 0 ? "Process1" : "Process2");
}
}
static void Method()
{
if (_random.Next()%2 == 0)
_eventHandles[0].Set();
else
_eventHandles[1].Set();
}
}
Идея 2
Вы также можете использовать один дескриптор события вместе с изменяемым полем, которое будет указывать, какой условный оператор был выполнен, чтобы выполнить соответствующий процесс после сигнала.
пример
enum Process
{
Process1,
Process2
}
static class Program
{
private static Random _random = new Random();
private static AutoResetEvent _eventHandle = new AutoResetEvent(false);
private static volatile Process _selectedProcess = Process.Process1;
static void Main()
{
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(Method);
threads[i].Start();
_eventHandle.WaitOne();
Console.WriteLine(_selectedProcess == Process.Process1 ? "Process1" : "Process2");
}
}
static void Method()
{
_selectedProcess = _random.Next()%2 == 0 ? Process.Process1 : Process.Process2;
_eventHandle.Set();
}
}
Идея 3
Если вы не можете изменить внешние компоненты и у вас есть только дескрипторы событий, то вы можете попробовать запустить новые потоки для каждого параметра и дождаться соответствующего сигнала для выполнения соответствующей операции.
пример
static class Program
{
private static Random _random = new Random();
private static AutoResetEvent[] _eventHandles = new[] {new AutoResetEvent(false), new AutoResetEvent(false)};
static void Main()
{
Thread[] processThreads = new Thread[2];
processThreads[0] = new Thread(Process1);
processThreads[0].Start();
processThreads[1] = new Thread(Process2);
processThreads[1].Start();
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(Method);
threads[i].Start();
}
}
static void Method()
{
if (_random.Next()%2 == 0)
_eventHandles[0].Set();
else
_eventHandles[1].Set();
}
static void Process1()
{
while (true)
{
_eventHandles[0].WaitOne();
Console.WriteLine("Process1");
}
}
static void Process2()
{
while (true)
{
_eventHandles[1].WaitOne();
Console.WriteLine("Process2");
}
}
}
Идея 4
Если процессам требуется небольшое количество времени, вы можете использовать метод ThreadPool.RegisterWaitForSingleObject
пример
static class Program
{
private static Random _random = new Random();
private static AutoResetEvent[] _eventHandles = new[] {new AutoResetEvent(false), new AutoResetEvent(false)};
static void Main()
{
ThreadPool.RegisterWaitForSingleObject(_eventHandles[0], Process1, null, Timeout.Infinite, false);
ThreadPool.RegisterWaitForSingleObject(_eventHandles[1], Process2, null, Timeout.Infinite, false);
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(Method);
threads[i].Start();
}
}
static void Method()
{
if (_random.Next()%2 == 0)
_eventHandles[0].Set();
else
_eventHandles[1].Set();
}
static void Process1(object state, bool timedOut)
{
Console.WriteLine("Process1");
}
static void Process2(object state, bool timedOut)
{
Console.WriteLine("Process2");
}
}
IDEA, которую я могу предложить, - это создать свой собственный EventWaitHandler, который может повторно использовать имя обработчика, позже это имя должно быть возвращено из метода Wait и работает как идентификатор вызывающей стороны.
для этого вы должны реализовать свой собственный метод Wait (я реализовал WaitNew для обслуживания и расширения WaitOne)
Смотрите следующий код для рабочего кода:
//Client application environments
public class WindowsApplication
{
public void ExecuteWindowsService()
{
var ws = new WindowsService();
var _eventHandle = new MyEventWaitHandler(false, EventResetMode.AutoReset, "WindowsApplicationMode");
ws.Execute(_eventHandle);
_eventHandle.Set();
}
}
public class WebApplication
{
public void ExecuteWebService()
{
var ws = new WindowsService();
var _eventHandle = new MyEventWaitHandler(false, EventResetMode.AutoReset, "WebApplicationMode");
ws.Execute(_eventHandle);
_eventHandle.Set();
}
}
//Windows Service Environment
public class MyEventWaitHandler : EventWaitHandle
{
public MyEventWaitHandler(bool initialState, EventResetMode mode, string name)
: base(initialState, mode, name)
{
this.EventHandlerName = name;
}
//it should not be set to empty string from external
public string EventHandlerName;
public string WaitNew()
{
if (base.WaitOne())
return EventHandlerName;
else return String.Empty;
}
}
public class WindowsService
{
public void Execute(MyEventWaitHandler _eventHandle)
{
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(Method);
threads[i].Start();
string name = _eventHandle.WaitNew();
if (name == "WindowsApplicationMode")
{
//Execute case for first process
}
else if (name == "WebApplicationMode")
{
//Execute case for second process
}
}
}
static void Method()
{
//Some Task
}
}
Дайте мне знать, если я правильно понимаю ваше требование?
Используйте WaitHandle.WaitAny для ожидания нескольких дескрипторов событий. Когда установлено одно или несколько событий, он вернет индекс события, вызвавшего возврат ожидания.
EventWaitHandle _ew1 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode1");
EventWaitHandle _ew2 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode2");
WaitHandle[] handles={_ew1, _ew2};
int index=WaitHandle.WaitAny(handles)
if(index==0)
{
// mode 1
}
else if(index==1)
{
// mode 2
}
Как насчет этого?
bool signaled = eventWaitHandle.WaitOne(TimeSpan.Zero);
Наследовать от EventWaitHandle
Добавьте изменчивое свойство "Caller". Каждый сигнализатор должен передать свой ID или Ref.
После сигнала, Interlock проверить имущество.