Как узнать, был ли вызван 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 проверить имущество.

Другие вопросы по тегам