Question

Is there a way to know which EventWaitHandle was invoked.

i have two custom class with 2 different System Wide Event names.

The reason I had them is to distinguish which function to trigger.

The problem I have right now is how can I distinguish which event was triggered?

EventWaitHandle _ew1 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode1");
EventWaitHandle _ew2 = new EventWaitHandle(false, EventResetMode.AutoReset, "Mode2");

So if _ew1.Set() is invoked then I need to execute Process1.

If _ew2.Set() is invoked then I need to execute Process2.

Update: Added More Info.

the main thread is a windows service. which is signaled by a web application and a desktop application. so basically the service needs to identify who triggered the event either from a web application or a desktop application if it's a WebAppliation then Execute SP1 else if it's a Windows Application then Execute SP2.

Was it helpful?

Solution

Idea 1

WaitHandle.WaitAny static method returns index of signaled wait handle, so the simplest solution would be to check that index.

Example

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();
    }
}

Idea 2

You can also use one event handle along with a volatile field that will indicate what conditional statement has been met in order to execute appropriate process after signal.

Example

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();
    }
}

Idea 3

If you are unable to modify external components and you have only event handles, then you may try start new threads for each option and wait there for respective signal in order to perform appropriate operation.

Example

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");
        }
    }
}

Idea 4

If processes require small amount of time, you can use ThreadPool.RegisterWaitForSingleObject Method

Example

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");
    }
}

OTHER TIPS

Use WaitHandle.WaitAny to wait on multiple event handles. When one or more of the events is set it'll return the index of the event that caused the wait to return.

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
}

An IDEA I can suggests is to create your own EventWaitHandler, that can reuse the name of handler, later this name should be returned from the Wait method and works as an identifier of caller

for this you have to implement your own Wait method (i implemented WaitNew to cater and extend WaitOne)

See the following code for working code:

//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
    }
}

Let me know if I understand your requirement correct?

Inherit from EventWaitHandle, add a volatile "Caller" property. Every signaller must pass his ID, or Ref.
After Signalled, Interlock check the property.

How about this?

bool signaled = eventWaitHandle.WaitOne(TimeSpan.Zero);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top