Click here to Skip to main content
15,883,901 members
Please Sign up or sign in to vote.
2.00/5 (1 vote)
See more:
I have a requirement to send notification events from Windows Service to a Windows console/Forms application using Named Events like Auto Reset Events and Manual reset events. For which I created a class library (WaitHandler) which has the definition for the Events. The windows client and service both have been reference by the class library in which the events are declared. The windows client waits at WaitOne() and the service need to raise an Set event so that windows client code can get into the loop. But When I try to raise the Set event, my client is not receiving it.

C#
public static class WaitHandler
    {
        private static System.Threading.ManualResetEvent manual = new     System.Threading.ManualResetEvent(false);
        private static System.Threading.AutoResetEvent auto = new   System.Threading.AutoResetEvent(false);

       public static System.Threading.AutoResetEvent GetAutoEventHandler()
       {
        return auto;
       }

    public static System.Threading.ManualResetEvent  GetManualEventHandler()
    {
        return manual;
    }
}


This is my code in Windows Service:

C#
public void RaiseEvent()
{
  WaitHandler.GetManualEventHandler().Set();
}


This is my code in Windows Client:

C#
public Form1()
   {
       InitializeComponent();
       new Task((o) => SubscribeToAsyncEvents(),
           new System.Threading.CancellationToken()).Start();
   }

   private void SubscribeToAsyncEvents()
   {
       while (true)
       {
           if (WaitHandler.GetManualEventHandler().WaitOne())
           {
               Console.WriteLine("Received Event");
               WaitHandler.GetManualEventHandler().Reset();
           }
       }

   }


Thanks
Posted
Comments
[no name] 12-Apr-15 3:52am    
I agree with SA. The statement that this method is a requirement is absurd (in the formal sense). The requirement is the outcome not the methodology. Named pipes are also a well tried method of IPC. https://msdn.microsoft.com/en-us/library/bb546085(v=vs.110).aspx

You are badly misusing the event wait handle objects. These events are used only to notify the thread in a wait state, to wake it up. Actually, this is not an "event" in the sense of something you can "send" and "receive", this is a way to throttle execution of some thread without any waste of CPU time (as it happens with spin wait): the thread waiting for the event wait handler object is switched out and is not scheduled back to execution until it is waken up by the event wait handler set by another thread. It also can be used for thread synchronization, to make one thread waiting for another thread to complete some part of work. As all blocking call, it should be used with great consideration and theoretical calculations of the application lifetime.

Also, manual reset right after waking up (or almost, as in your case) can be considered as another abuse. (But it depends on what you try to achieve.) You could use System.Threading.AutoResetEvent. The functionality is no the same as in your seemingly "simulated" auto reset. It is impossible to guarantee simulation AutoResetEvent's reset with ManualResetEvent reset: auto resetting mechanism guarantees that exactly one thread at a time is passed through the point when the thread is waken up; the second thread will be always blocked again.

Your static class-factory methods are totally redundant: if you want to choose auto or manual reset depending on condition, you could use the base class System.Threading.EventWaitHandle and control the type of reset using its constructor, one of the constructors using EventResetMode argument: https://msdn.microsoft.com/en-us/library/system.threading.eventwaithandle%28v=vs.110%29.aspx.

Your RaiseEvent method is correct (however, it's not clear why writing a separate method, but it's OK), but you did not show where you called it. It will really wake up the thread blocked at the wait for the event wait handler. It all depends on when you call it. But main thing is: there is no such thing as "receive" this kind of event.

See also my past answers on this topic and on the purpose of these classes:
ManualResetEvent and AutoResetEvent in Thread,
pause running thread,
Making Code Thread Safe.,
Running exactly one job/thread/process in webservice that will never get terminated (asp.net)..

Now, these classes are mostly used for thread synchronization for the threads of the same process. For IPC, there are many different facilities. I would like to mention one which is often forgotten: sockets. Remember that, historically, sockets have been developed purely as IPC facility, only later used for networking. This is still a very good and flexible IPC tool. Please see:
https://msdn.microsoft.com/en-us/library/system.net.sockets%28v=vs.110%29.aspx.

—SA
 
Share this answer
 
v3
Comments
CSharpNewbie 2 11-Apr-15 21:47pm    
Thank you Sergey, I am trying to signal a windows forms application from a Windows Service using the named events. I understand AutoResetEvents and ManualResetEvents are mainly used for thread synchronization, but now I have a requirement to use named events to signal a Windows Forms application. After reading your comment I started looking into EventWaitHandler and modifed my code and Here it is

Windows Service Code:

public void SetSignalToClient()
{

System.Threading.EventWaitHandle wh = EventWaitHandle.OpenExisting("MyEventName", EventWaitHandleRights.Modify);

wh.Set();
}

Windows Forms Application:
public void ReceiveSignalFromClient()
{
textBox1.Text = "Successful";
while (true)
{
EventWaitHandle wh = new EventWaitHandle(false, EventResetMode.AutoReset, "MyEventName");
wh.WaitOne();
textBox1.Text = "Failed";
}

}

But, my service is crashing with an exception. Please let me know if I am missing something.In Event Viewer I found the exception as: System.Threading.WaitHandleCannotBeOpenedException
Sergey Alexandrovich Kryukov 11-Apr-15 21:53pm    
What exception? where? Could you move this code to the body of your question, to make it more readable?

No matter what you do, the whole idea is total abuse, the idea to wait in cycle. You cannot ask for an advice and say "this is requirement" in part of implementation, you can only explain your ultimate goals and ask for the advice on implementation. Otherwise, please ask those who gave your the "requirements". What you do makes no sense.

—SA
CSharpNewbie 2 11-Apr-15 22:00pm    
I moved the same question below...I also updated it with the exception.System.Threading.WaitHandleCannotBeOpenedException
Sergey Alexandrovich Kryukov 11-Apr-15 22:08pm    
Okay, this is simple: this exception is invoked when the named object you are trying to open using this name does not exist. You just did not created it, at least not at the moment of the call.
—SA
Here is the solution using the EventWaitHandle to achieve synchronization between multiple processes. I am posting it so that it could be helpful to somebody else.

Used the below two links to achieve the task of notifying client application from a windows service. After using the below, please make sure to use the 'Global\" prefix while creating the event as the Windows Services run in session 0, and user applications run in session 1 or higher. So for a service and a user application to communicate, they must use global objects.

http://blogs.msdn.com/b/mattdotson/archive/2006/03/03/543143.aspx[^]

https://msdn.microsoft.com/en-us/library/z4c9z2kt(v=vs.110).aspx[^]
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900