I have developed a C# application which makes heavy use of events. Now this application is occasionally doing funny things that I cannot understand or track down to a specific cause why they should occur. I reckon that the cause for these intermittent malfunctions is some sort of concurrency or race condition which I did not anticipate.
How exactly are events handled in C#? If an event is raised, will (a) the portion of code attached to that event be executed immediately? Or will the event (b) be put on a stack of events and be executed whenever .NET deems it suitable for execution while other code is executed in the meantime?
If an event is raised, will the portion of code attached to that event be executed immediately?
Well, yes and no. Events are multicast delegates, so there might be zero, one or many "portions of code" attached to an event. In the scenario where there are many, clearly one of them has to go first and one of them has to go second. The one that goes second isn't executed immediately upon the event being raised; it's executed immediately upon the first event handler completing normally.
will the event be put on a stack of events and be executed whenever .NET deems it suitable for execution while other code is executed in the meantime?
Suppose your application is badly written and hangs the UI. While the UI is hung, the user clicks on button 1 and button 2. Since the application is hung, nothing visible happens. The events for button 1 and button 2 being clicked do not fire. But Windows has created a message queue and enqueued on it the fact that button 1 and button 2 have pending clicks that need to be processed when the application unhangs itself. When the message loop is pumped then the button 1 click event fires. When it is done doing its thing, the message loop is pumped again and the button 2 click event fires.
So yes, in that sense events are queued up and executed later, but it is not "when .NET deems it suitable"; it's when the thread that is processing the message queue starts processing the message queue again. There's no mysterious Windows policy in here controlling your code.
It entirely depends on the event raising (and subscription) code.
If you're raising the event like this:
EventHandler handler = MyEvent;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
or something similar, then all the event handlers will be executed immediately. That's the typical implementation... you have to work a bit harder to put each event delegate into WinForms message queue or something like that.
If you could give us more information about what events you're talking about and how they're implemented, we may be able to help you more.
For more information on events and delegates (and the difference between them) you may wish to read my article on the topic.
C# events, just like the rest of delegates, are executed immediately when triggered.
Unless explicitly implemented otherwise, events are called synchronously.
Typically the code that triggers an event looks like that:
public event EventHandler MyEvent;
protected virtual void OnMyEvent()
{
EventHandler handler = MyEvent; // keep a copy to avoid race conditions
if (handler != null)
handler(this, EventArgs.Empty);
}
As you can see from this code, event handlers are called immediately and synchronously from the OnMyEvent method.
I believe your question has been answered here:
Are Event Handlers processed Asynchronously?
In short, it depends on your implementation, but the default event handling is processed synchronously. There are, however, ways to make it asynchronous.
As stated in the previous awnser, it entirely depends on the code that is raising the event or handeling the event.
What above examples are missing is properly code on how to raise/handle events. I'm aware that they're just quick examples, but nonetheless, good practise is important.
If you want good examples/material on how events can be properly processed in C#, you could take a look at this article: http://www.codeproject.com/KB/cs/event_fundamentals.aspx
Related
I have an event handler that for some reason (I don't understand) get called twice, I thought that setting e.Handled = true will solve it but it doesn't, finally I unsubscribed from the event inside the handler, and it works:
((FabTabItem)sender).TabClosing -= oTab_TabClosing;
So I have these questions:
What is the difference between the both approches, Don't they stop handling the event?
Is it OK to unsubscribe from the event inside its handler since its natural to say "stop listening to the event after it's been handled"? (I don't see this a lot)
From the following MSDN page on the KeyPressEventArgs.Handled Property:
If the event is not handled, it will be sent to the operating system for default processing.
So setting it to true means that any further processing of the event will not happen for the rest of that call to the event depending on how the other events handle the Handled property. As #Enigmativity put it in the comments to the OP:
When you have several handlers for the one event they are called in series. If one of the handlers thinks that it has "handled" the event and no further handlers need to do anything it can set e.Handled = true. It is up to the subsequent handlers to honour this flag and not do any processing - but they are still called. Also this doesn't change the handling for when the next time the event is raised - all of the handlers get called again.
By unsubscribing from the event the rest of the actions in the event still occur, in the case of the above mentioned event it still goes through to the operating system.
The two scenarios you described are not exactly the same.
Unsubscribing from the event inside the handler itself is fine, all it does is remove the call to that handler next time the event is raised.
With that said if you are doing this because the event is being called more times than it should be you should probably track down where the event is being subscribed too. It is likely you have accidentally subscribed the same handler twice and that is the proper fix rather than hacking around it by unsubscribing from the event.
What is the difference between the both approaches, Don't they sop handling the event?
e.Handled = true; indicates that the event handler has already processed the event and dealt with it, so it doesn't need to be processed any further. In other words, please don't take any further action.
but the second will Remove Event and Don,t happen next time
Is it OK to unsubscribe from the event inside its handler since its natural to say "stop listening to the event after it's been handled"? (I don't see this a lot)
its depend to your Roll if you want not happen after a If use handle but if you want never happen after if use second
and remove event
I have a MVVM application in WPF. I have an event that gets dispatched from a static instance of a class.
When a given condition occurs, I need to listen for the next occurrence of said event. I do this with the following code:
myInstance.OnData += myEventHandlerInstance;
The event handler is removed at a later time, but as soon as it is added, the event handlers in the other view models no longer execute. I have verified that the dispatcher is the same instance in all places where the event is fired and handled (using the methods described below).
Why does the existing handler not get executed?
delete this line:
myInstance.OnData -= new EventHandler(myInstance_onData);
Why were you doing this? You should get the original event handler and remove that. Also, you should do this outside the event handler itself.
You'll have to put in something like this, to ensure that your code is executing on the right thread:
if(Dispatcher.CurrentDispatcher.CheckAccess())
{
<Code here>
}
else
{
Dispatcher.CurrentDispatcher.Invoke(<Code here>)
}
Thanks for the help everyone. You helped me focus in on the problem. The problem was purely a structure/logic issue, I was able to dig deeper into the code.
Often in code I see a line of code, I have an idea it do something about event but not clearly know what it does.
Is it possible that I can attach form A's load event in Form B with this, or what is its benefit?
this.CGForm .Load +=new EventHandler(CGForm_Load);
Yes, it clearly has to do with events.
.Load in this case the the Form.Load event. The += operator adds one event handler to the event. An event can have many event handlers at the same time. Event handlers are just regular method that can be anywhere in your code base. When the event fires all subscribed methods will be called, one after the other.
I see no particular good reason to have FormA listen to the Load event of FormB, but other events might be more interesting, like the Form.Closed event. This is a way to have FormA react to changes in FormB.
Edit
Note that this causes FormA to hold a reference to FormB and FormB won't be garbage collected until FormA releases the reference to FormB (with
this.CGForm .Load -=new EventHandler(CGForm_Load);, note the -=) this is a common cause for memory leaks in .NET.
Subscribing to events from other forms is a "code smell" that can be a potential structure problem with your code. In some cases it is required, but if you have it all over the place your code will be hard to understand and maintain.
What this line means is that you subscribe the method CGForm_Load() to the this.CGForm.Load event. The method CGForm_Load() is the event handler or the callback.
After you run this line, every time the event is raised (in this case - every time the form is loaded), CGForm_Load() will be called automatically.
In order to unsubscribe a callback, use -= like this:
this.CGForm.Load -= new EventHandler(CGForm_Load)
Once an event callback is unsubscribed, the next time the event is raised (if the form is loaded again) the callback will no longer be called.
I find the following metaphor helpful: An event is like a power outlet, and callbacks are like power plugs. Subscribing is like connecting the plug to the outlet, and unsubscribing is like pulling it out. While there is a connection, all invocations of the event trigger the callback.
It simply adds the GCForm_Load method to the Load event on the CGForm. Under the hood when the CGForm is loaded code like the following will execute. Whenever this happens all event subscribers (in this case the method being subscribed here as CGForm_Load) will be invoked.
<pseudocode>
class CGForm
{
public EventHandler<FormLoadedEventArgs> Load;
private void SomeMethodThatLoadsTheForm()
{
LoadForm();
var loadHandlers = Load;
if (loadHandlers != null)
{
loadHandlers(new FormLoadedEventArgs(...));
}
}
}
</pseudocode>
this.CGForm .Load +=new EventHandler(CGForm_Load); subscribes the event handler delegate CGForm_Load to the Load event of the CGForm object.
Documentation about subscribing to events can be found at http://msdn.microsoft.com/en-us/library/ms366768(v=vs.80).aspx .
And index of information about how events work in .NET can be found at http://msdn.microsoft.com/en-US/library/awbftdfh(v=VS.80).aspx
In a C# winforms program, I have an event that fires when someone attempts to rename a project. In the EventArgs for that event, I have a "Cancel" property that the event listeners can set to true to (ideally) cancel the rename (if the name is already in use, for example):
ProjectRenamedEventArgs args = new ProjectRenamedEventArgs(oldName, newName);
if (NameChanged != null)
NameChanged(this, args);
if (args.Cancel)
{
// Cancel
}
else
{
// Continue
}
The problem is, the "if (args.Cancel...." line is never reached. I'm guessing that execution is continuing right after the event is fired, and thus args.Cancel is always false so the rename always happens. How would I make execution halt until all of the event listeners have finished their work (giving args.Cancel a chance to be set to true).
I am assuming this is possible because many of the windows forms EventArgs have a Cancel property that allow for whatever just happened to be cancelled (changing the label on a TreeView's TreeNode, for example).
You say: "The problem is, the 'if (args.Cancel...." line is never reached'
This tells me that your event handler(s) wired to NameChanged are not returning. Another possibility is that one of these handlers is throwing an unhandled exception, and the above code in your example is swallowing the exception.
-Oisin
Events are synchronous by default = you current code should work.
You need to use BeginInvoke to make events asynchronous (the thingy that you want to avoid)
How would I make execution halt until all of the event listeners have finished their work
It does halt until all handlers have executed, it's the default behavior if you call NameChanged directly. Try to step into the event handlers to see what's happening
The only reason for not calling if (args.Cancel) ..
i can think of is that there is an uncaught exception inside one of the eventhandlers.
Note i sometime have problems with the vs2008/vs2010 debugger that continues operation of the main app instead of stopping behind the event-call. you can check this if you put a breakpoint at
if (args.Cancel) ..
What will happen when 10 threads will subscribe to the same event and the event fires?
Which thread will pick it up?
Thread's don't subscribe to events, objects do. When an event fires, all of the registered handlers execute on the same thread (the one that raised the event). There's no built-in facility for events to fire on multiple threads.
A handler can choose to forward the event information to a separate thread, if desired, but that's not part of the built-in mechanism of event dispatch.
If by "event" you mean a Win32 synchronization Event (which is how I read the question) then it depends on how the EventWaitHandle is created. If its manual reset, the event will signal all threads and all will execute. If its auto reset, a single thread will be signalled and executed. Any of your 10 threads waiting on the event could be chosen.
I think what you mean here is that multiple objects on separate threads subscribe to an event.
All of the handlers will be called but on the same thread that invoked the event.
The answer to your question I guess is it depends on the implementation of the event dispatcher... Usually you use a list to keep track of all the event handlers which subscribed to a particular event, so most likely in terms of this kind of implementation, the first handler that gets fired is the first event handler that got subscribed if you of course call all the relevant procedures synchronously, if not, then it depends... just a thought..
If you want to know which object will pick up the event, every object that subscribes to an event will pick up that event, but each will run on the thread that the event occurred on.
If you want to know which object will pick up that event first see ultrajohns answer.
I think if I understand your question. You mean to ask your object exposes a event that user of your object can subscribe. If 10 different users of your object has subscribed to this event, and at some point you fire the event, what would be order (or simultaneously) the event handlers would be invoked?
Answer: Since the event handler execution happens on the same thread who fires it (in this case your object's processing thread) can only process one handler function at a time. The order is not guaranteed (meaning not necessarily first subscriber would executed first and last would be executed last). I hope this answers your question. The bottom line is all 10 handler would be called and none would be in parallel. They will be executed one after another. I have seen people accidentally subscript to save event twice and then seeing the action happening twice and having hard time figuring out why some things are happening multiple times.