event driven methods and execution sequence in c#.NET - c#

Hypothetically speaking, if I had two methods (event handlers) driven by the same event, which method is executed first?
Example:
obj.SomeEvent += new SomeEventHandler(method1);
obj.SomeEvent += new SomeEventHandler(method2);
Which is called first?
Thanks!

It's up to the event publisher, but usually it would be whichever handler was added to the event first. That's the default implementation for an event which is basically implemented using a delegate. So for example:
SomeDelegate eventHandlers = null;
eventHandlers += FirstHandler;
eventHandlers += SecondHandler;
eventHandlers(...);
That will definitely call FirstHandler before SecondHandler. However, there's no guarantee that an event will be implemented just using delegates like that.
EDIT: While the event handling behaviour is up to the event publisher, the delegate combination part is well-specified in the C# language specification, section 7.8.4:
[...] Otherwise, the result of the operation is a new delegate instance that, when invoked, invokes the first operand and then invokes the second operand.
The BCL Delegate.Combine method makes a similar guarantee (emphasis mine):
(Return value) A new delegate with an invocation list that concatenates the invocation lists of a and b in that order. Returns a if b is null, returns b if a is a null reference, and returns a null reference if both a and b are null references.

The first subscribed one. "First in - first served".

The default implementation will cause event handlers to be called in the order they were added, however, it is possible to customize this behaviour. If the behaviour is customized, the client cannot tell this. So the real answer to your question is that the order in which event handlers is raised "depends" and could even change at runtime, however, the vast majority of events have default implementation.
For example:
public class ReverseBling
{
private readonly List<EventHandler> _blings = new List<EventHandler>();
public event EventHandler Bling
{
add
{
_blings.Add(value);
}
remove
{
_blings.Remove(value);
}
}
public void RaiseBling()
{
for (int i = _blings.Count - 1; i >= 0; i--)
{
_blings[i](this, EventArgs.Empty);
}
}
}
private static void Main()
{
ReverseBling bling = new ReverseBling();
bling.Bling += delegate { Console.WriteLine(0);};
bling.Bling += delegate { Console.WriteLine(1); };
bling.Bling += delegate { Console.WriteLine(2); };
bling.RaiseBling();
}
Output:
2
1
0

There is no way of telling which event handler will be invoked first. Many people think the first one to subscribe will be invoked first (which is normally the case) but not specified by the CLI.

Related

attaching handler that returns a value to an event c#

I have the following:
public String AttachService(string whereClauseParam)
{
//Get Client object here
Client c = new Client();
string cookieFromRequest = WebOperationContext.Current.IncomingRequest.Headers[HttpRequestHeader.Cookie];
tokenInfo.TryGetValue(cookieFromRequest, out c);
string[] arr = new string[] { };
c.AttachedServiceStatus += OnAttachedServiceStatus;
string whereClause = whereClauseParam.ToString();
//c.AttachService("binding.interface='query_em'", 8799989);
return string.Format("attached");
}
//Handler code below:
public string OnAttachedServiceStatus(Client sender, ClientServiceAttachedStatus status)
{
if (status.AttachStatus == AttachedStatus.Connected && status.ServiceAttachStatus == ServiceAttachStatus.Attached)
{
//update the Client object in Dictionary
Client c = new Client();
var ou = tokenInfo.First(x => x.Value == sender);
tokenInfo.TryGetValue(ou.Key.ToString(), out c);
tokenInfo.TryRemove(ou.Key.ToString(), out c);
tokenInfo.TryAdd(ou.Key.ToString(), sender);
string[] statusInfoT = new string[200];
statusInfoT[0] = status.ServiceId.ToString();
statusInfoT[1] = status.AttachStatus.ToString();
statusInfoT[2] = status.ServiceAttachStatus.ToString();
statusInfoT[3] = status.VirtualServiceId.ToString();
statusInfoT[4] = status.AttachToken.ToString();
statusInfo.TryAdd(ou.Key.ToString(), statusInfoT);
//update the UI with a Dispatch - TO BE DONE
}
return "Connected";
}
The above AttachService method has a handler "OnAttachedServiceStatus" attached to an event "AttachedServiceStatus".
As long as the OnAttachedServiceStatus return void, it all works well. However, i now need to have the Handler OnAttachedServiceStatus to return a string but i'm not able to attach the handler correctly.
I'm thinking of using the Func delegate but not sure how to use it.
Please Help!
First of all, signature of event handler is defined by event's delegate type. If that delegate returns void, then you cannot attach any other methods. Both parameters of method and return value should match signature of even's delegate. I believe AttachedServiceStatus uses delegate which returns void. Something like that:
public delegate void Action<T1, T2>(T1 arg1, T2 arg2)
And event is
public event Action<Client, ClientServiceAttachedStatus> AttachedServiceStatus
But what if you'll use delegate which returns value? E.g.
public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2)
You can declare event as
public event Func<Client, ClientServiceAttachedStatus> AttachedServiceStatus
But it makes no sense. Because event is a delegate. When you attach handler, you are actually combining delegates, creating something like list of delegates (invocation list). This list contains all attached handlers. When you raise event, all handlers in invocation list are invoked one by one, and only result of last invoked handler is returned. Order of invokation is not determined. So you even don't know which handler returned value.
(*) Though it is still possible to get all results if you will invoke each handler manually instead of raising event. See Servy comment below
UPDATE
I want the handler "OnAttachedServiceStatus" to return a string back
to Caller "AttachService" but i cannot get the following correct
When you attach handler to event, handler is not executed. It just added to invocation list of event. Event handler will be executed when Client will raise event. So AttachService is not a caller here. Client is a caller. And you cannot return string back to AttachService. After attaching handler to event, code will exit AttachService method. Some time later event will be raised, and handler will be executed, but it will not be related to AttachService method.
I'm not sure you're understanding how events work.
Client c = new Client();
// ...
c.AttachedServiceStatus += OnAttachedServiceStatus;
OnAttachedServiceStatus is not being called here. Instead, this is telling the Client object to invoke the OnAttachedServiceStatus method whenever it raises the AttachedServiceStatus event, which may happen at any point in the future. It's like you telling a racer "When I say 'go', run as fast as you can to the finish line then tell me how many steps it took you to get there". The racer doesn't immediately start running at that point, nor do they tell you how many steps it took; they get in the ready position and wait. When you say "go", that's when they execute your instructions and start running. By the time you get their response, it's well after you gave him the instruction to wait.
From the looks of things, you're attempting to establish a remote connection and are wanting confirmation back from the server that a connection has indeed been established. If using events to convey that information, you'll want to use the EventArgs to carry it. You should be able to achieve that with something like this:
Client side:
public String ConnectToServer(string whereClauseParam)
{
//Create Server object here
Server s = new Server();
s.AttachedServiceStatus += OnAttachedServiceStatus;
s.AttachService(this, whereClauseParam, 8799989);
}
public void OnAttachedServiceStatus (object sender, ClientServiceAttachedEventArgs e)
{
if (e.AttachStatus == AttachedStatus.Connected && e.ServiceAttachStatus == ServiceAttachStatus.Attached)
{
// Update the UI with the message from the server.
MessageBox.Show(e.Message);
// If you need to do something else with the server in response, you can do this:
((Server)sender).Foo("bar");
}
}
And on the server side, define the custom EventArgs class for your event:
// By making this inherit from EventArgs, we can use the built-in EventHandler<T> delegate for the event itself.
public class ClientServiceAttachedEventArgs : EventArgs
{
public AttachedStatus AttachStatus { get; set; }
public ServiceAttachStatus ServiceAttachStatus { get; set; }
public string Message { get; set; }
// You can put in as many properties as you want to carry the information back from the server.
}
And put this in your Server class:
public event EventHandler<ClientServiceAttachedEventArgs> AttachedServiceStatus;
public String AttachService(Client client, string whereClauseParam, int code)
{
// Do what you need to do to register the client.
//...
// Assuming everything went as planned, fire the event.
// First, construct the EventArgs with information about the results of the connection.
ClientServiceAttachedEventArgs e = new ClientServiceAttachedEventArgs();
e.AttachStatus = AttachedStatus.Connected;
e.ServiceAttachStatus = ServiceAttachStatus.Attached;
e.Message = "Attached";
// This is where your OnAttachedServiceStatus method in the client finally gets called. If the event handler were returning a string, this is where it would be returned to and I can't imagine this does you any good.
AttachedServiceStatus(this, e);
}
This is a fairly basic implementation and your situation is probably more complex but it should point you in the right direction. The important thing to note is that the string that you wanted returned back to the client is coming through the event as part of the ClientServiceAttachedEventArgs, along with your status enums. This is the preferred way of sending information through events.

Why should I check for null before I invoke the custom event?

What is the difference between these two code samples for invoking an event?
Sample 1
public void OnDataChanged()
{
if (DataChanged != null)
{
DataChanged(this);
}
}
Sample 2
DataChanged.Invoke(this);
When should I use each method to invoke a custom event? And why sometimes I get a NullReferenceException when I try to invoke event using DataChanged.Invoke(this), but when I convert the event invocation to the method in Sample 1 the DataChanged never becomes null anymore?
An OnXYZ method should always follow this form:
public void OnXYZ()
{
var evt = XYZ;
if (evt != null)
evt(sender, e); // where to get e from differs
}
There are a couple of reasons for this form:
The if evt != null check ensures that we don't try to invoke a null delegate. This can happen if nobody has hooked up an event handler to the event.
In a multithreaded scenario, since delegates are immutable, once we've obtained a local copy of the delegate into evt, we can safely invoke it after checking for non-null, since nobody can alter it after the if but before the call.
What to pass for e differs, if you need to pass an EventArgs descendant with a parameter there are two ways:
public void OnXYZ(string p)
{
var evt = XYZ;
if (evt != null)
evt(sender, new SomeEventArgs(p));
}
or more commonly this:
public void OnXYZ(SomeEventArgs e)
{
var evt = XYZ;
if (evt != null)
evt(sender, e);
}
This syntax:
evt(sender, e);
is just a different way of writing this:
evt.Invoke(sender, e);
Also note that externally to your class, the event is an event, you can only add or remove event handlers from it.
Internal to your class, the event is a delegate, you can invoke it, check the target or method, walk the list of subscribers, etc.
Also, in C# 6 there is a new operator introduced, ?. - the Null-conditional operator - which is basically short for if not-null, dereference, which can shorten this method:
public void OnXYZ(SomeEventArgs e)
{
var evt = XYZ;
if (evt != null)
evt(sender, e);
}
into this:
public void OnXYZ(SomeEventArgs e)
{
XYZ?.Invoke(sender, e);
}
which can be further shortened with the use of Expression-bodied members:
public void OnXYZ(SomeEventArgs e) => XYZ?.Invoke(sender, e);
Please note that it is not possible to write this:
XYZ?.(sender, e);
so you must in this case use Invoke yourself.
when I convert the event invocation to the method in Sample 1 the DataChanged never becomes Null
Then you're simply looking at two different scenarios.
if you don't declare an event like public event EventHandler YourEvent = delegate { };, then YourEvent is null until some consumer subscribes to it.
If nothing has subscribed to DataChanged it will be set to null, and so when you attempt to do DataChanged.Invoke(this) you'll get a NullRefException as really it's trying to do null.Invoke(this). The reason for the additional if (DataChanged != null) is to avoid this occurring when nobody has subscribed to the event.
I don't believe that when you use Sample 1 DataChanged is never null, it's just never reaching the .Invoke to throw up the exception. It will always be null if nobody has subscribed.
Are you sure, that in Sample 1 the DataChanged is never null? Or you just don't get the NullReference Exception (because you check if DataChanged is not null in the if statement)?
Let's start with the basics. Event is a special kind of delegate. When you call DataChanged(this) and DataChanged.Invoke(this), it's the same thing. Why? Because it compiles to the same thing. So all in all the DataChanged(this) is just a shorthand for calling DataChanged.Invoke(this).
Now, why do we need to check for null reference (like in sample 1).
Basically, when you invoke an event, you invoke all methods that were subscribed to this event (e.g. DataChanged += someEventHandler).
If nobody subscribed to this event, it will have a null value. No method was assigned to handle this event. In other words: the event handler is null.
That's why it's a good practice to check for null, before invoking an event.
An Example:
public void OnAbc(){
var data=Abc;
if(!String.IsNullOrEmpty(data))
Abc(sender,e);
}

Decompiled assembly - unusual code

I decompiled an assembly using ILSpy, and one class in particular got my attention:
public class CustomTextStream : NetworkStream
{
private EventHandler<CustomEventArgs> someEvent;
public event EventHandler<CustomEventArgs> SomePublicEvent
{
add
{
EventHandler<CustomEventArgs> eventHandler = this.someEvent;
EventHandler<CustomEventArgs> eventHandler2;
do
{
eventHandler2 = eventHandler;
EventHandler<CustomEventArgs> value2 =
(EventHandler<CustomEventArgs>)Delegate.Combine(eventHandler2, value);
eventHandler =
Interlocked.CompareExchange<EventHandler<CustomEventArgs>>(
ref this.someEvent, value2, eventHandler2);
}
while (eventHandler != eventHandler2);
}
remove
{
// similar stuff...
}
}
}
Further in the code, seems like private delegate is used to fire an actual event:
if (something != null && somethingElse != 0)
{
this.someEvent(this, new CustomEventArgs(someArg));
}
The question: Can someone guess what could be the idea behind this custom accessors, assuming that some "compile/decompile magic" didn't take place? I'm not much familiar with IL, btw...
(Side note: the application is multi-threaded and utilizes networking, obviously.)
This is a new event handler code generated by compiler. It was introduced in C# 4 (C# 3 version was different)
Interlocked.CompareExchange compares first argument with third, and if they are equal, replaces first argument with second. This is a thread-safe operation. Loop is used for a case when after assigning a variable eventHandler2 and before check, another thread changes this delegate. In this case, Interlocked.CompareExchange does not perform exchange, loop condition does not evaluate to true and next attempt is made.
C# 3 generated simple code in event handlers:
add { lock(this) { changed = changed + value; } }
Which had lower performance and could introduce deadlocks.
There is a great series of articles on this subject:
Events get a little overhaul in C# 4
Events get a little overhaul in C# 4, Part II

Pass an event as a parameter to a method [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to pass an event to a method?
Is it possible to pass an event as a parameter to a method?
For example, the following method subscribes to the event, does work, and unsubscribes from the event:
void SubscribeDoAndUnsubscribe<TElement, TEventArgs>(
IEnumerable<TElement> elements,
??? elementEvent)
where TEventArgs: EventArgs
{
EventHandler<TEventArgs> handler = (sender, e) => { /* Handle an event */ };
foreach (var element in elements)
{
// Subscribe somehow
element.elementEvent += handler
}
// Do things
foreach (var element in elements)
{
// Unsubscribe somehow
element.elementEvent -= handler
}
}
Client code:
var elements = new [] { new Button(), new Button() };
SubscribeDoAndUnsubscribe(elements, ??? /* e => e.Click */);
If it's not possible, how do I achieve the similar logic in other ways? Shall I pass pair of delegates for subscribe/unsubscribe methods?
You have in fact discovered that events are not "first class" in C#; you cannot pass around an event as data. You can pass around a delegate to a method associated with a receiver as a first-class object by making a delegate. You can pass around a reference to any variable as a (mostly) first-class object. (I say "mostly" because references to variables cannot be stored in fields, stored in arrays, and so on; they are highly restricted compared to other kinds of data.) You can pass around a type by obtaining its Type object and passing that around.
But there is no way to directly pass around as data an event, property, indexer, constructor or destructor associated with a particular instance. The best you can do is to make a delegate (or pair of delegates) out of a lambda, as you suggest. Or, obtain the reflection object associated with the event and pass that around, along with the instance.
No, unfortunately not.
If you look at Reactive Extensions, that suffers from a similar problem. Three options they use (IIRC - it's been a while since I've looked):
Pass in the corresponding EventInfo and call it with reflection
Pass in the name of the event (and the target if necessary) and call it with reflection
Pass in delegates for subscription and unsubscription
The call in the latter case would be something like:
SubscribeAndDoUnsubscribe(elements,
handler => e.Click += handler,
handler => e.Click -= handler);
and the declaration would be:
void SubscribeDoAndUnsubscribe<TElement, TEventArgs>(
IEnumerable<TElement> elements,
Action<EventHandler<TEventArgs>> subscription,
Action<EventHandler<TEventArgs>> unsubscription)
where TEventArgs: EventArgs
You're trying to get around type safety, and you can't do so without using reflection. I'll show you an even simpler example of what you're trying to do.
void DoSomethingOnSomethingElse(T obj, Action method)
{
obj.method();
}
C# doesn't work this way. How does the compiler know that all Ts have the method method? It doesn't, and can't. Similarly, not every TElement in your code will have an event Click for example.
It sounds like you just want to set a single use event handler on a set of objects. You can do this quite easily...
EventHandler handler = null;
handler = (s,e) =>
{
DoSomething(e);
var b = (Button) s;
b.Click -= handler;
}
foreach (var button in buttons)
{
button.Click += handler;
}
This, obviously, only works with buttons, but as I write this, I see Jon Skeet has shown you a more general solution, so I'll end here.

When is it better practice to explicitly use the delegate keyword instead of a lambda?

Is there any best practice with respect to coding style with respect to explicit use of the delegate keyword instead of using a lambda?
e.g.
new Thread(() =>
{
// work item 1
// work item 2
}).Start();
new Thread(delegate()
{
// work item 1
// work item 2
}).Start();
I think the lambda looks better. If the lambda is better style, what's the point of having a delegate keyword, other than for the fact that it existed before lambdas were implemented?
Lambda syntax is much more generalised, and the designers have said that they'd ideally remove the old overlapping syntaxes (dont have a citation, but it's probably Eric Lippert or Jon Skeet in a book or a podcast).
But delegate allows you to ignore parameters, e.g.:
object.Event += delegate { };
versus having to say:
object.Event += (sender,args) => { };
which can be very useful in large argument lists and/or to make the code more resilient to refactoring.
EDIT: As pointed out by Yann Schwartz in another answer (now unfortunately deleted), a very neat usage of this trick is in order to provide a default hander for an event using the Null Object pattern:-
class MyClassThatFiresWithoutTheTrick
{
public event EventHandler MyEvent; // implicit = null
// Need a method to keep this DRY as each fire requires a null check - see Framework Design Guidelines by Abrams and Cwalina
protected virtual void OnMyEvent()
{
// need to take a copy to avoid race conditions with _removes
// See CLR via C# 3rd edition p 264-5 for reason why this happens to work
//var handler = MyEvent;
// BUT THIS is the preferred version
var handler = Interlocked.CompareExchange( ref MyEvent, null, null);
// Need to do this check as it might not have been overridden
if( handler == null)
return;
handler( this, EventArgs.Empty );
}
}
class MyClassThatFiresWithTheTrick
{
public event EventHandler MyEvent = delegate{};
protected virtual void OnMyEvent()
{
MyEvent( this, EventArgs.Empty );
}
}
(though what you might often end up doing is an Inline Method of OnMyEvent, making the code even shorter again.)

Categories

Resources