run action after an event is completed in .NET/C# - c#

Action1
triggers Event1
Event2
in this order.
Action2 also triggers Event2.
I need to execute a method after Event1 is triggered AND COMPLETED.
How would I achieve this in C#/.NET?
The key is that I need to execute that method when the event is completed, because only then I have access to certain properties of an object.
I was thinking of adding a variable globally at class level and assign it a value inside Event1 handler.
Then checking inside Event2 handler if the variable was initialised, which means we are at a stage where Event1 was completed. And then inside Event2 handler adding my method.
This doesn't seem to work because Event2 is triggerred extremely often when Action2 is executed (an action I don't care about) and I get a stack overflow error message.
Is there a good way to actually make this work?
Can(how) I do something like override the library and add a new event (that does nothing) triggered when an existing event is completed; then I would use the new event just to attach a handler to it and put my method there.
These events and actions are inherent to a framework so I don't have much control over them as their definition is hidden inside .net libraries.
So I'm interested in some general principles and tricks and these are the limitations/setbacks.
Some sample code can be found here: https://stackoverflow.com/questions/41969955/how-to-use-invoke-to-call-a-method-after-an-event-was-finished

Event handling is by its nature synchronous (assuming somebody doesn't use async void or start their own thread in a handler) so the following code:
Event1?.Invoke();
//Do stuff after Event1
Will already do what you are asking. If you need to wait for some asynchronous task that is kicked off by a handler of Event1 then you will need to do that apart from the event invocation process.

Related

Where should events be raised?

I'm not new to C#, but events is one of the most confusing topics I confront in the language.
one of the questions is: where should I assign the event handler to the event, or the question in other form: why most events are raised in the subscriber constructor? what does it mean?
like this example (taken from the book Mastering Visual C# )
public ReactorMonitor(Reactor myReactor)
{
myReactor.OnMeltdown +=
new Reactor.MeltdownHandler(DisplayMessage);
}
Raise = generate. Events are not raised in the subscriber constructor. The subscriber does not raise events at all. The event source raises/generates events, and subscribers subscribe to, receive, and handle them.
Events in c# are nothing more than function pointers, i.e. a variable that contains a pointer (or list of pointers) to a function that matches a specific signature (typically Action<object,EventArgs>). Or in the words of this MSDN article:
Delegates are like C++ function pointers but are type safe.
When you subscribe to an event, you are essentially saying "Store the address of my function. When X happens, please call it (along with any other function whose address is stored)."
Thus the code
myReactor.OnMeltdown += Meldownhandler;
can be read as
objectThatRaisesEvents.FunctionPointer = MyHandler;
Notice that MyHandler is not followed by parentheses. If it were MyHandler() that means you are invoking the function, the value of the expression MyHandler() is actually the return value of the function; MyHandler by itself doesn't invoke the function or return its value but instead returns the address of the handler itself. So the above line of code takes the address of MyHandler and stores it in a variable named FunctionPointer.
When the object that raises events invokes FunctionPointer() it is telling c# to obtain the address of the function stored in FunctionPointer and invoke it.
So it is really calling MyHandler() indirectly. Thus these two lines do exactly the same thing:
objectThatRaisesEvents.FunctionPointer();
MyHandler();
Also notice the += in your example. In c# that is the equivalent of
objectThatRaisesEvents.FunctionPointer =
objectThatRaisesEvents.FunctionPointer + MyHandler;
We typically use that syntax because there might be several handlers that subscribe to an event. += has the effect of appending our handler to the list. You could use = instead, but it would unsubscribe any existing handlers.
To answer your question-- when should you subscribe to events? That is a very broad question, but typically
In an ASP.NET web page, you'd subscribe during the Init event.
In a Windows Form, you'd subscribe in the InitializeComponent method.
There are many other contexts of course... the bottom line is you should subscribe before you need to receive notifications of occurrences of the event.
The event is one of the standard features of .NET Framework built using delegate model implementing the Observer design pattern.
https://msdn.microsoft.com/en-us/library/edzehd2t(v=vs.110).aspx
https://en.m.wikipedia.org/wiki/Observer_pattern
Where you subscribe to the event depends on the business rules, but most of the time you want to subscribe at the earliest possible moment which is usually the constructor of the class interested in the handling of the event.
When events should be raised on the other hand depends on what you are trying to communicate to the subscribers if it is a notification of the state change then you raise an event as soon as state is changed.
An event is a message sent by an object to signal the occurrence of an
action. The action could be caused by user interaction, such as a
button click, or it could be raised by some other program logic, such
as changing a property’s value.

How does C# eventhandler work internally?

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.

When does the loadoperation completed event fire?

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.

Clever event accessors - to fire handlers on the thread they were registered?

Have just had an idea, I haven't seen it before, wondering if you guys thought it was a good idea, if it exists, any common pitfalls etc. - and also how to implement it.
There are several times I've found myself subscribing to an event from the UI thread that will be called from a different thread - for example, notification of a service call completing.
'My' idea would be to store the current Dispatcher in the add block along with the handler delegate, then when the event is 'fired', perform some extra logic/checks to see if there was a dispatcher associated with the handler, and Invoke on it if necessary.
Of course it would only work on threads with a Dispatcher (or Forms equivalent - something with a message pump I guess). I guess the usefulness and cleanliness depends on whether the event subscriber should have to worry about the thread the handler is called or not?
Edit: Sounds like it's not such a bad thing then - additionally does anyone have any idea how to implement? Using Delegate.Combine how could you call each handler on a different Dispatcher, for example? Would you instead store delegates in a composite object in a List, and invoke them in turn in the On(Whatever) method, or is there something nicer?
...Looking at the BackgroundWorker source in Reflector, there's nothing to Invoke:
protected virtual void OnProgressChanged(ProgressChangedEventArgs e)
{
ProgressChangedEventHandler handler = (ProgressChangedEventHandler) base.Events[progressChangedKey];
if (handler != null)
{
handler(this, e);
}
}
Unless I'm missing something?
So then BackgroundWorker does it with an AsyncOperation. How about a general solution, just for event handlers, in the event accessors? BackgroundWorker can get away with the way it works because a method is called from the client - in the more general case, the only time you'll have access to the handler's thread is in the event accessor? :)
As far as I know, that's exactly what the BackgroundWorker is doing in its RunWorkerCompleted and ProgressChanged events. So it can't be that bad.
I can't find a real proof, that the BackgroundWorker is doing it, I just read it somewhere. When you google for it, you will find more hints. If someone can provide a link, I would be happy.
UPDATE:
Because it isn't so easy to find this behavior in the BackgroundWorker, I provide my analysis:
The BackgroundWorker is using an AsyncOperation for raising the events. Inside this class, the events are posted to a SynchronizationContext. Only then are the methods OnProgressChanged and OnRunWorkerCompleted executed. This means, those methods are already executed on the right thread.
In some more detail, the following happens, when RunWorkerAsync is called:
An AsyncOperation instance is created via AsyncOperationManager.CreateOperation. This saves the current SynchronizationContext. As we are still in the UI thread, this is the context of the UI thread.
The background operation is started and calls into the private method WorkerThreadStart. This method is running in the background thread and executes OnDoWork which in turn raises the DoWork event. This means, the DoWork event is not raised in the UI thread.
After OnDoWork completed, the PostOperationCompleted method of the AsyncOperation instance is executed which in turn calls AsyncOperation.Post which calls SynchronizationContext.Post which in turn will call indirectly OnRunWorkerCompleted on the UI thread.
When ReportProgress is called, a similar thing happens: AsyncOperation.Post is called directly and will invoke the OnProgressChanged method on the UI thread.
AsyncOperation and AsyncOperationManager are public and can be used to implement a similar behavior in your classes.
I've done something similar with Castle DynamicProxy, where it intercepts calls and does an IsInvokeRequired/Invoke on them.

C# .NET 3.5 : How to invoke an event handler and wait for it to complete

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.

Categories

Resources