Say I have the following code:
public event EventHandler DatabaseInitialized = delegate {};
//a intederminant amount of subscribers have subscribed to this event...
// sometime later fire the event, then create a new event handler...
DatabaseInitialized(null,EventArgs.Empty);
//THIS LINE IS IN QUESTION
DatabaseInitialized = delegate {};
Will this clear out the subscribers, replacing it with new empty default? And, will the event notify all subscribers before they get cleared out? I.E. Is there a chance for a race condition?
Yes it will clear it out. And because events fire syncronously in the same thread there shouldn't be race condition.
My advice: when in doubt, write a small test application and... well, test it.
UPDATE: I tested it before posting. (In response to minuses.)
To unsubscribe from the event use event-=delegate, so you're sure that resource is free. Even if by official Microsoft documentation it's not necessary, in my own experience, especially on a large scale complex project, unnecessary events suscribers are source for memory leaks. So unsubscribe from them explicitly.
Related
i recently created a sample application, wherein i implemented the events and delegates, when the Properties value is changed this event will raise, i have a question regarding events
Does event objects are created in memory? or they are just static object which gets removed once the event is fired?
Is it necessary to remove the handler once the event is executed, to free-up resources. does removing handler once done, boost's up the application performance, i am talking about the application which are using lots of events
Events do take memory and are not garbage collected until after you unsubscribe from them. They are a common cause of memory leaks.
Events can be both static and instance bound. Subscribers to the event are never removed while the event broadcaster is alive, unless implicitly done so, usually with the -= operator.
Yes, yes and yes. If you don't clean-up your subscribers you have a memory-leak waiting to happen.
If all this is a concern to you perhaps you could look into the WeakEvent pattern.
events are like delegates ( with another layer of protection) .
when you register to an event - you are actually making a reference to another object.
this object can't go through GC because you made a reference to it !
it isnt "un-referenced".
but your object CAN go through GC. ( if un-referenced).
so you end up with memory leak.
you should manually remove the reference .
I guess C# eventhandler has a list of listeners and it loops thru the list when sending a message. My question is how does this works in internally. Does it make a copy of the list before looping it thru and if so, what happens if someone unregister itself after the list has been copied but it has not yet received the message.
Will it still get the message even do it has unregister itself?
A delegate is immutable, so when you are invoking a delegate the list of subscribers is known and fixed. Subscribing or unsubscribing replaces the delegate that underpins the event.
This does indeed mean that in a multi-threaded scenario you can receive an event after unsubscribing, because either:
the delegate was already in the process of being invoked
a snapshot of the delegate had already been obtained for the purpose of invoking
by 2, I mean the usual pattern (to prevent a null-ref during invoke):
var handler = SomeEvent;
// <===== another thread could unsubscribe at this point
if(handler != null) handler(sender, args); // <== or part way through this invoke
// (and it either case, have the event trigger even though they think they have
// unsubscribed)
For that reason, if you are coding complex multi-threaded code with events, you should code defensively such that the event firing after you think you have unsubscribed is not a problem.
These nuances do not really impact single-threaded code.
Class DomainContext has method Invoke which return instance of InvokeOperation
and often we can see next code
InvokeOperation op = domainConextInstance.Invoke(...);
op.Completed +={...};
My first thought - it should not work: after all event can arise earlier than we will subscribe for it.
I made an experiment
InvokeOperation op = domainConextInstance.Invoke(...);
Thread.Sleep(5000); //or 25000
op.Completed +={...};
But I found that this code works correctly, But how?
Can you explain this to me?
And what pattern does this construct use?
It's hard to know without seeing any of the code for DomainContext - but it sounds like the code which adds a handler for the Completed event calls the handler immediately if the operation has already completed.
Assuming you have the code for InvokeOperation, I'd definitely look at the declaration of the Completed event to discover the "magic".
Assuming, you are talking about WCF RIA Services SDK, Jon is right. InvokeOperation has a property IsComplete. The add part of the Completed event checks this property. In case of a completed operation it does not add the passed event handler but calls it immediately.
You can validate this by inspecting OperationBase (base class of InvokeOperation) in System.ServiceModel.DomainServices.Client.dll with a disassemler tool like dotPeek.
Let's say I have a collection of thousands of objects, all of which implement the following:
public event EventHandler StatusChanged = (s,e) => {};
private void ChangeStatus()
{
StatusChanged(this, new EventArgs());
}
If no handlers are subscribed to that event for each object, does using the no-op event handler provide any performance drawbacks? Or is the CLR smart enough to ignore it? Or am I better off checking for a StatusChanged handler before firing the event?
Yes, the CLR is not really smart enough to ignore it but the difference should be negligible in most cases.
A method call is not a big deal and is unlikely to have a meaningful impact on the performance of your application.
If your application calls ChangeStatus thousand times per second, maybe it would be a problem. But only profiler can prove this.
I have a class containing a worker thread which receives data from a queue in a loop.
Another part of the app sinks an event from this class, which the class raises for each queue item.
These events are fired asynchronously, so at busy times the other part of the app can be processing several events at once.
This should be fine but we've discovered a scenario where this can cause problems.
We need a quick solution while the main issue gets addressed. Does the framework provide a simple way I can force the worker thread to wait while each event gets processed (so they are processed sequentially)? If not, what's the easiest way to implement this?
A simple answer would be to lock() on a single object in the event handler. All of the theads would wait to get the lock.
The ManualResetEvent class might help you here, unless I'm not understanding your question. You can use it to block the firing of the next event until the last one completes.
My guess is that you want to simply go away from triggering the action by raising an event and calling the method directly.
AFAIK events are going to be async and I am not aware of any "easy" ways of changing that.
Turns out there's another answer. You can just add the following attribute to the method.
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]
There is no general way.
In the end the handlers need to provide a mechanism for tracking.
If you are using BeginInvoke, rather than raising the events directly, you can use a wrapper, within which you call the real event handler synchronously, then raise the wrapper asynchronously. The wrapper can maintain a counter (with Interlocked operations) or set an event as meets your needs.
Something like:
TheDelegate realHandler = theEvent;
var outer = this;
ThreadPool.QuereUserWorkItem(x => {
// Set start of handler
realHandler(outer, eventArgs);
// Set handler finished
};
All of the event handlers sinking events raised by the queue-reading worker thread are called in the queue-reading worker thread. As long as the event handlers aren't spawning threads of their own, you should be able to wait for the event handlers to finish by calling Thread.Join() on the queue-reading worker thread.