You may be familiar with using this class in a single application in many cases to synchronize threads, BUT what if we took this class a step further and used it in a strange way that is often overlooked? Just consider for a moment that you are building your application and you would like to share special events to other applications well refer to them as subscribers. Similar to (Windows Messaging) without the window handles and message queues?
Have a look at the table below to become familiar with some keywords.
Client
The main application or owner. Regardless of what this application does it can offer the ability to share events to others if they wish to subscribe as a (subscriber).
Subscribers
Subscribes to the owner(client) to receive events when the client signals.
- "" title="Building the client and discussing important factors that need to be considered."]
In order to begin building your client we'll need a WaitHandle object.
EventWaitHandle Class
http://msdn.microsoft.com/
Know your event mode
The idea is to create what is known as a "named event object". The subscribers can use the name to subscribe to your events in there own applications. Now before going further it's important to understand the difference between how a particular event mode works.
AutoReset
When signaled, the EventWaitHandle resets automatically after releasing a single thread. If no threads are waiting, the EventWaitHandle remains signaled until a thread blocks, and resets after releasing the thread.
ManualReset
When signaled, the EventWaitHandle releases all waiting threads and remains signaled until it is manually reset.
It's important to choose the right type of event mode for your client. If you decide to use an AutoResetEvent then only one subscriber will be notified for each call made to .Set() which means if you have multiple subscribers and the client calls .Set() once only one subscriber is notified. This would require your client to know how many subscribers it is working with so it can call the .Set() method as many times as needed for the number of subscribers. In this particular case we want the ability to notify everyone without knowing how many subscribed.
The ManualReset event is the clear winner since our client can call .Set() once to notify all subscribers then immediately call .Reset() to put them back into there respective waiting cycle.
No, you as a subscriber can't play, tinker, or change my events. They're mine!
It's important that when setting up your clients event object you only allow subscribers the ability to Wait or Synchronize with your event. If you don't take the steps to ensure the proper access rights on your event many bad things can happen. Ever hear the phrase "one bad apple spoils the whole bunch?" Well, one bad subscriber can ultimately take control and tinker with your events by setting them to non-signaled or taking ownership. This is important especially if you decide to hand out your event object's name. Even better would be to randomly generate an event name and add it to the atom table and have them pull the name from the table. This ensures your client would have been the first one to create the named event reducing the likelihood of a bad apple opening the named event for the sole purpose of causing havoc to running subscribers. In reference to some applications opening the named event before the client, it's very unlikely this would ever happen but it's something that should be mentioned. However security on your event is absolutely necessary.
The client can accomplish security using the following classes.
EventWaitHandleSecurity
EventWaitHandleAccessRule
Put the client into practice
Hopefully the above information made you a little more familiar with how the clients named event should be played out. Now we can put that information into practice. The Client in the following example is simply a Windows Form Application and a button with a touchy trigger finger.
Create new Windows Form Application
Add one button to the form
Set the button caption:Trigger
In the code above we created a named event object called EEArticle and set strict rules for how subscribers can access our object. In this case any and all subscribers have the ability to synchronize or (wait) until the client signals the event. If a subscriber attempts to open the event with any other type of access they should be ashamed of themselves and be denied dinner for the night.
- "" title="Building the subscriber. Discuss how a subscriber can subscribe to the client."]
Now that you have built your client with good security measures, it's time to give subscribers the ability to subscribe to your client. In order to do that you can share your clients event name. In our client example that is: EEArticle
There is not much that changes for subscribers. Like the client, the subscriber also uses the EventWaitHandle Class but in a slightly different manner. Since the client is known as the owner, the subscriber needs to open the existing named event object.
The subscriber uses the shared EventWaitHandle.OpenExisti
In order for the subscriber to wait for signals from the client, they can use one ThreadPool and register the named event with the ThreadPool. The ThreadPool will wait until the client signals the event object. When this occurs it sets our open event object into a signaled state, the ThreadPool fires off into a specified callback and we as a subscriber are notified whenever the client decides to get a touchy trigger finger. The way that we set up the ThreadPool initially will automatically re-wait for additional events until we choose to UnSubscribe.
Put the subscriber into practice
The subscriber in this example is simply a Windows Form Application with nothing added to the form but the subscriber code itself.
Real World Example
Scratching the surface
Hopefully you found this interesting. Just how useful this type of mechanism becomes depends on how far you are willing to take this example and improve upon it. On the surface this particular example in the article is not extremely useful but you could use Named Shared Memory and use this approach to synchronize when your client writes information into the shared view, allowing subscribers to pick up the information (a structure) and use it to their heart's content. This is just one approach that could be used to share information between processes or simply informing child applications or others that a particular (action) has occurred in your application.
To create named shared memory and extend this example into passing something useful to your subscribers you may want to consider using the new MemoryMappedFile Class which has only been introduced with .NET 4.0 framework.
MemoryMappedFile Class
http://msdn.microsoft.com/
The Client uses:
MemoryMappedFile.CreateNe
http://msdn.microsoft.com/
The Subscriber uses:
MemoryMappedFile.OpenExis
http://msdn.microsoft.com/
In this respect the example starts to become more useful as when the client writes information into the shared memory it can notify subscribers that new information is available. The subscriber can pick up the new information and work with it any way it chooses.
Final thoughts
The goal of this article is to show how the WaitHandle class can be used differently instead of only thinking about them as something internal to your single application. There are better alternative ways to (IPC) this is just another way thinking outside the box and taking a single class and making something interesting. Many coming to the .NET world might not know how events can be used and there purpose, those that are familiar can look at this article and see something in .NET that they probably have never seen done before after all programming is about having fun and coming up with funky ideas.
:)