Raising events in C# from classes - c#

Basically I am attempting to write a generic interprocess communication implementation between C# and the Android platform (using Java).
Creating the socket stack is simple enough but what I am wondering is what would be a good pattern to passing in delegates into my TcpServer class and raising the required events.
The idea so far is.
while (connected) {
//Compile all the required data and so forth
switch (currentState)
{
case CurrentServerState.EventReceived:
//Raise my event...
break;
case CurrentServerState.ObjectReceived:
break;
}
}
So would the correct implementation simply expose an array of delegates and use reflection to match event names or something along those lines? What are my options? Also how do I make sure that any raised events are raised in the UI thread given that this is all occurring from a thread created for the server?

If you don't need to pass any custom arguments to the event handler you can use the default EventHandler delegate which uses the base EventArgs.
Declare the events you want to make available like this:
public event EventHandler EventReceived;
public event EventHandler ObjectReceived;
Declare a protected method for each event to handle raising the event for you. This is really just a convenience to keep from repeating this each time you need it. You could do this inline.
Your events will be null if there are no attached event handlers. The method handles checking for this before firing the event.
protected void RaiseEventReceived(EventArgs e)
{
if (EventReceived != null)
EventReceived(this, e);
}
Then call the method when you want to raise the event. The method will handle checking to see if anyone is listening for the event.
public void SomeOtherMethod()
{
while (IsConnected)
{
switch (CurrentState)
{
case CurrentServerState.EventReceived:
RaiseEventReceived(EventArgs.Empty);
break;
case CurrentServerState.ObjectReceived:
RaiseObjectReceived(EventArgs.Empty);
break;
}
}
}
You can declare your own class to pass custom arguments to the event handlers by deriving from EventArgs such as the following. By convention your class should be named *something*EventArgs.
public class EventReceivedEventArgs : EventArgs
{
// Declare properties to hold additional event info here
}
Then you would need to declare a custom delegate that takes your new event args parameter:
public delegate void EventReceivedEventHandler(object sender, EventReceivedEventArgs e);
Update your event declarations to use your new delegate type instead of EventHandler:
public event EventReceivedEventHandler EventReceived;
And finally, when raising the event you of course would want to create a new instance of your custom event arguments class and intitialize your custom properties.
Clients can attach multiple handlers to your events using the normal syntax and they will always be called on the correct thread.

Related

EventHandler<T> and EventHandler

I want to ask the different between EventHandler and EventHandler<T>.
Previously I have implemented a EventHandler, with a custom EventArgs which can be passed to the parent page from the user control.
I thought I need to apply EventHandler< T >, however it can be implemented by using EventHandler. (in fact there is weird error when I trying to apply EventHandler<T>, the program is worked but error is shown in the IDE which I couldn't solve [C# Custom EventHandler ])
Thus, I want to know in what situation I need to apply EventHandler < T > ?
public event EventHandler AppendProcess;
public event EventHandler<MyEventArg> AppendProcess;
---Update---
this is how I invoke the event in the user control (as i said, i can pass object to parent page by doing this (although i don't know if it is correct to do so)
if (AppendProcess == null) { }
else
AppendProcess(this, new Common.WinLose_ProgressStage(Common.WinLose_SP_Parameter.upper, displayLevel + 1,
(int)Common.WinLose_Level.lvChild4, thename, refundratio,
selfproportion, -1, -1, loadlevel, isPlayer, betsource, gamecategory, false));
EventHandler<T> is just a generic EventHandler type, which avoids you having to declare a new delegate type for each kind of EventArgs you want to use.
Consider Control.KeyPress for example. It's declared as an event of type KeyPressEventHandler. That delegate is just declared as:
public delegate void KeyPressEventHandler(object sender, KeyPressEventArgs e)
If EventHandler<T> (and generics) had been around when that was created, the event could have been declared as an EventHandler<KeyPressEventArgs> instead, saving a delegate declaration. There are many, many delegates which are just like EventHandler, and only vary in the type of the second parameter - EventHandler<T> avoids that redundancy.
No if you don't have your own custom EventArgs subclass, there's no reason to use EventHandler<T>... but if you do, it's much better to use it, so that the method handling the event receives your custom EventArgs subclass in a strongly-typed way.
As an aside, your way of invoking the event handler isn't thread-safe. Another thread could unsubscribe the final event handler after your nullity check. If you're using C# 5, you should write it as:
var handler = AppendProcess;
if (handler != null)
{
handler(this, new Common.WinLose_ProgressStage(...));
}
If you're using C# 6 or later, you can use the null conditional operator:
// If AppendProcess is null, the arguments won't even be evaluated
AppendProcess?.Invoke(this, new Common.WinLose_ProgressStage(...));
EventHandler<T> is the generic variant of EventHandler. Usually, you would override EventArgs and EventHandler to come up with an own event type. You still need to derive EventArgs if you want to pass in custom properties to the e argument, but you don't need to create a custom delegate for EventHandler any more. You now can just say:
public event EventHandler<SomeEventArgs> SomeEvent;
Which is more convenient than:
public delegate void SomeEventHandler(object sender, SomeEventArgs e);
public event SomeEventHandler SomeEvent;
When your delegate signature doesn't change, EventHandler<T> is much more straightforward to use.
From your other question:
Common.WinLose_ProgressStage wps = (Common.WinLose_ProgressStage)e;
That's a cast that could potentially fail, depending on how the method is invoked. There is nothing guaranteeing that your event handler only gets called with Common.WinLose_ProgressStage that can be inspected without checking your full program. It could be called with a plain EventArgs too: you made that possible by making the parameter type EventArgs.
EventHandler<T> causes more compile-time type checking. If other code attempts to pass in EventArgs.Empty, the call would simply fail to compile.
It's basically the same as "why shouldn't I make all my parameters of type object"? Sure, you could do that. And if you do that, casting back wherever needed, your code would work. But I know I prefer
long Add(long x, long y) { return x + y; }
over
object Add(object x, object y) { return (long)x + (long)y; }
and I suspect that in this case, you do too. Yet this is exactly what you're doing when you make the parameter type EventArgs rather than Common.WinLose_ProgressStage.

Simplest way to handle creating events in a class

While playing around in VS 2015, i was creating a property and mistyped prior to hitting tab and it gave me what appears to be a very clean simple method for creating an event. I am unsure how to use this to accept additional parameters to pass it data (as I usually want to pass data when raising an event with information about what is in progress, or what was done)
The code it gave is as follows :
public event EventHandler<EventArgs> MyEvent;
protected virtual void OnMyEvent(EventArgs e)
{
EventHandler<EventArgs> handler = MyEvent;
if (handler != null)
handler(this, e);
}
At first glance it is similar to most examples however this method does not appear to require a delegate to operate. Compare with the following example from How to call an event manually in C#?
public delegate void MyEventHandler(object sender, MyEventArgs e)
public event MyEventHandler MyEvent;
public void RaisesMyEvent()
{
if(MyEvent != null) //required in C# to ensure a handler is attached
MyEvent(this, new MyEventArgs(/*any info you want handlers to have*/));
}
What I would like to know, in light of having more elegant (clean) code, is the method that microsoft provided (first method in this question) better (it seems cleaner), and if so, how could I adjust it slightly to accept a string in addition to standard event args and/or extend the eventargs to pass information ?
To pass custom arguments on an EventHandler, you would create your own class derived from EventArgs and change the declaration like so:
public event EventHandler<MyCustomEventArgs> MyEvent;
Alternatively, if you don't like having object sender in your handlers, you can do:
public event Action<MyCustomEventArgs> MyEvent;
or even
public event Action<string> MyEvent;
As far as the invocation, Microsoft's is better. The reason is that the null check you wrote isn't thread-safe. Storing off the handler before doing the null check ensures that you don't invoke a null method.
Alternatively, use C# 6 invocations and take advantage of the null conditional operator:
MyEvent?.Invoke(whateverArgs);
The code that Visual Studio auto-generated for you is actually better for one small condition:
public void RaisesMyEvent()
{
if(MyEvent != null) //required in C# to ensure a handler is attached
// Now if someone in another thread sets MyEvent to null the next line will still execute
MyEvent(this, new MyEventArgs(/*any info you want handlers to have*/));
// And throw a NullReferenceException
}
This code has a race condition. It's fairly rare to hit it, but it is possible. The Visual Studio boilerplate code avoids this race condition by making a local copy of the event handler before calling it.
As for how to pass more parameters to the event handler:
There are multiple ways, but the 'standard' way is to create an class that extends EventArgs. For instance, PaintEventArgs extends EventArgs and adds a Graphics and Rectangle properties for the OnPaint handler to use.
I'd follow that basic pattern by creating a MyEventArgs class based off EventArgs, and adding the properties your method will need to use.
Just replace EventArgs with your own class:
class MyEventArgs : EventArgs
{
public string Text { get; private set; }
public MyEventArgs(string text)
{
Text = text;
}
}
The EventHandler<T> generic delegate type will accept EventArgs or any subclass of EventArgs.
Then when you call OnMyEvent(), just pass an instance of your class with the data you want to deliver with the event.
I agree with the other notes regarding thread-safe invocation. This isn't always required, but it's simple enough to implement and the IDE-provided version is safe while yours is not.

Difference between private EventHandler and private event EventHandler?

Basically what the title says.
Whats the difference between those two (I am currently using the first one)
private EventHandler _progressEvent;
and
private event EventHandler _progressEvent;
I have a method
void Download(string url, EventHandler progressEvent) {
doDownload(url)
this._progressEvent = progressEvent;
}
The doDownload method would call the
_progressEvent(this, new EventArgs());
It works fine, so far. But I feel I am doing something horribly wrong.
The first defines a delegate, the second defines an event. The two are related, but they're typically used very differently.
In general, if you're using EventHandler or EventHandler<T>, this would suggest that you're using an event. The caller (for handling progress) would typically subscribe to the event (not pass in a delegate), and you'd raise the event if you have subscribers.
If you want to use a more functional approach, and pass in a delegate, I would choose a more appropriate delegate to use. In this case, you're not really providing any information in the EventArgs, so perhaps just using System.Action would be more appropriate.
That being said, an event approach appears more appropriate here, from the little code shown. For details on using events, see Events in the C# Programming Guide.
Your code, using events, would likely look something like:
// This might make more sense as a delegate with progress information - ie: percent done?
public event EventHandler ProgressChanged;
public void Download(string url)
{
// ... No delegate here...
When you call your progress, you'd write:
var handler = this.ProgressChanged;
if (handler != null)
handler(this, EventArgs.Empty);
The user of this would write this as:
yourClass.ProgressChanged += myHandler;
yourClass.Download(url);
For private, there is no difference between the two, but for public you would want to use event.
The event keyword is an access modifier like private internal and protected.
It is used for restricting access to multicast delegates. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/event
Going from most visible to least visible we have
public EventHandler _progressEvent;
//can be assigned to from outside the class (using = and multicast using +=)
//can be invoked from outside the class
public event EventHandler _progressEvent;
//can be bound to from outside the class (using +=), but can't be assigned (using =)
//can only be invoked from inside the class
private EventHandler _progressEvent;
//can be bound from inside the class (using = or +=)
//can be invoked inside the class
private event EventHandler _progressEvent;
//Same as private. given event restricts the use of the delegate from outside
// the class - i don't see how private is different to private event

Action<T> is different event Action<T>?

public class TestA
{
public event Action<int> updateEvent;
...
if(updateEvent != null)
{
Actin<int> tempEvent = updateEvent;
updateEvent(1);
}
}
public class TestB
{
public Action<int> updateEvent;
...
if(updateEvent != null)
{
Actin<int> tempEvent = updateEvent;
updateEvent(1);
}
}
however event Action<T> is eventQueue au
use same and resutl same. What is more good? (i like TestB. Because simple using.)
The event modifier is useful to prevent an assignment. What does it mean? If that's a callback with many handlers attached you may want to prevent that someone simply write:
myObject.UpdateEvent = null or something like that. With event they can't do that. Take a look at Learning C# 3.0: Master the fundamentals of C# 3.0.
The code you use to call the event isn't bad but not so useful, if you assign the delegate to temporary variable you may want to be somehow thread-safe (someone could unhook after your null check) so you should do it before the check:
Action<int> tempEvent = updateEvent;
if (tempEvent != null)
tempEvent(1);
A little side note: if you use events you may want to follow .NET Framework patterns and guidelines, take a look at MSDN
To the compiler, the difference is that the event cannot be invoked except by the declaring class (like a private member). You can use either in the same way.
To design, events should represent their namesake, i.e. events. Think of a Delegate as just the type or signature of methods. You would declare a class to have an event (of type Action), and you would add (subscribe) to that event other Actions (or methods that can be cast to an Action).
Furthermore, it is common practice to create events of a type that inherits from EventHandler<T>
An event is just a delegate with some access wrappers.
The problem with your TestB is that because the updateEvent delegate is public, ANYONE can fire the delegate, not just the class owning it.
Defining it as an Event as in your TestA, client code can only subscribe or unsubscribe to the event, they cannot fire it.
ps. You do not need your tempEvent delegates.

How do I extract an event handler to another file and still have access to sender and args?

I attached an event handler to Entity Framework's SavingChanges event. Now, I found out I need to attach the same event handler somewhere else in the solution. Both situations (maybe even more if we dig deeper) require the same code so it makes sense to extract to a method and call the same method from multiple event handlers.
The method body includes references to the sender object and eventargs. How do I pass these parameters to the method, even when it's in its own class ?
The sender and event arguments should be part of your method signature and will be passed to the method you are writing when the event is fired. So the variables are defined as parameters to your event handler, and the values for those will be sent by the event trigger.
// I don't know what the proper signature is for a SavingChanges event handler
public class EventHandlers
{
public static void SavingChangesHandler(object sender, EventArgs args)
{
// do something with sender and args here
}
}
// in your other code
SomeObject.SavingChanges += EventHandlers.SavingChangesHandler;

Categories