How To Use Events In Controls For Mutual Communications? - c#

This is a question about programming techniques. The idea is this:
control A fires events (normal)
control A listens to events (of other threads / controls)
I want to implement the 2nd one. But in a safe and most modular way. So the control mustn't know who is firing the event only that it is fired. I think there are lots of ways to do that. Which one is the best ? Let's say a form is firing the event LoadImages and wants to listen to event ImagesLoaded.
threads / controls call a function of control A and notify it in this way that they'are done (but they know about control A and it's methods)
control A subscribes to events of threads / controls and knows when they are fired (master thread that knows about everything must connect them via event subscribing)
control A starts a waiting thread that calls a blocking function and fires the ImagesLoaded event at the end when the function is done (control A knows about threads / controls that do some jobs)
control A calls either a function or fires an event while passing a callback function as parameter (no one knows anything except what they have to do)
... ?
Which one gives me most modularity ? Are there even more ways to implement 2 ?

The technique you mentioned is usually achieved by asynchronous calls and *callback*s that are executed when the asynchronous call is completed. Having said that, it seems like BackgroundWorker fits your situation. You can execute blocking/long-running jobs with its DoWork handler and bind what's to be done when it's finished to RunWorkerCompleted event (updating the UI especially).

Related

How to detect when the visual tree is destroyed?

In a WPF application I have, I have a control that is central to the application. This control, called ArtView, is visible for the entire lifetime of the main window. It performs hardware accelerated rendering, and in order to avoid bogging down the UI thread, I set up an event loop in the OnLoaded handler for this control. Events such as mouse clicks, keyboard input, and scrolling are added to a queue that is then consumed by the event loop, but the problem I have is that I do not know how to end the event loop when the window is closed. When I close the window that contains the control, OnUnloaded does not fire, so what is the best way to disable the event loop when the control is no longer visible?
I am aware that I can do something like Window.GetWindow(this).Closing += OnWindowClosing; but that feels like a hack.
dymanoid's solution of subscribing to IsVisibleChanged works flawlessly, and provides a more satisfying solution than depending on the Window for the cleanup of my control.

Keydown event not firing in user control obj

I have a user control which is not declared in the designer. I have a button that I want to have create this user control when I click it - it should initialize the user control and insert it in the main UI.
However, it happens that the user control has a key press event on it, which is not firing.
Why does this happen?
I already tried to attach the event on the user control itself but it seems that it's not firing at all. Is there some kind of bug?
It is very hard to fix problems with code that you can't see, but in WPF, there are often reasons why Bubbling events like the KeyDown event don't fire. Occasionally certain controls may make use of these events and set them as handled internally, thereby stopping them from bubbling up any further.
The normal solution on these occasions is to use the related Tunneling events instead, which are raised before the Bubbling methods and not used internally by controls. So, while I can't guarantee that this will fix your problem, it is certainly worth trying to handle the UIElement.PreviewKeyUp event instead of the UIElement.KeyUp event.

Is there any way to get an event handler to run directly on UI thread without intermediate threadpool thread?

I have an event that is fired async via BeginInvoke - so the event handler gets its own threadpool thread. But all the code in the event handler wants to be dispatched to the UI thread - so the entire event handler code is in a Dispatcher.BeginInvoke block. This means:
Initiating thread fires event with BeginInvoke.
A new threadpool thread is created for the event handler code to run on.
The event handler immediately just posts its code async to the UI thread using
the dispatcher (Dispatcher.BeginInvoke(...all handler code...).
The temp threadpool thread returns quasi immediately - its created only to do a UI thread post.
Is there any way to restructure this to avoid the creation of this very short lived intermediate threadpool thread (I.e so the handler code just runs directly on the UI thread)?
I dont want the event to fire sycnronously (Invoke) - its used in various contexts - and it shouldn't be blocking.
Can you just call Dispatcher.BeginInvoke directly instead of using a threadpool thread?
If you don't control the code that fires the event you don't really have a choice; there is no way around the use of the thread pool thread for that short duration.
If you do control the code that fires the event you have the option of ensuring that the event handlers all run in the UI thread. While this is certainly possible, you should think long and hard about whether it should be the case. For certain event handlers it just makes sense for them to run in the UI thread (as an example, most of the events of Form run in the UI thread) and some it doesn't. If your event is on a UI control it probably makes sense for it to run in the UI thread. If it's an event of some worker class that you just happen to be using from a UI thread at the moment, it's probably a bad idea to fire the event in the UI thread (as you may, in the future, be using that worker context in a non-WPF context).
If you do want to fire the event in the UI thread it's simple enough. If you are already in the UI thread when you intend to fire the event just invoke it synchronously:
var eventCopy = MyEvent;
if(eventCopy != null) eventCopy();
If you're not in the UI thread when you wish to fire the event then marshal to the UI thread before calling the above code:
Dispatcher.BeginInvoke(()=>{ //Or just `Invoke`, if that's appropriate in context
var eventCopy = MyEvent;
if(eventCopy != null) eventCopy();
});
Based on your edit it seems you want to conditionally fire the event in the UI thread or a thread pool thread based on some specific context, rather than always firing in the UI thread.
While this is possible, you'll need to decide if it's worth it.
As an example you could look at System.Timers.Timer which has a SynchronizingObject property that allows you to determine how the events are rasied (null for the thread pool, or an object capable of marshalling to a particular context in the event of a particular UI model).
You could follow that general pattern.
There are a number of specific methods. You could capture the value in SynchronizationContext.Current at the time your worker thread was first created, and use that (possibly with a boolean value to disable capturing the source sync context if you might need to disable it, or forcably enable it).
Another option is to just have a property that accepts a SynchronizationContext, or some other mechanism of marshalling code to a given context (you could invent your own, use delegates, etc.).

When exactly are events executed in C#?

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

Multiple Threads subscribing same event

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.

Categories

Resources