I am developing an application that is split into multiple .NET assemblies (one main executable and a set of class libraries). Currently, I am using a WPF GUI, but I need to maintain the flexibility to possibly switch to another GUI framework at a later time.
Here is my problem: one of the class libraries performs some work on a separate thread, and raises an event when that thread is complete. I quickly discovered that my WPF GUI got upset when I tried to modify its components from this event handler, so I implemented an "event queue" that dispatches events on the main thread using a System.Windows.Threading.DispatcherTimer. This did the job; however, I was horrified to discover that this DispatcherTimer only works within the context of a WPF application!
I am trying to hide all the ugly details of multithreading within this class library, which may eventually be used in conjunction with a non-WPF GUI. The idea is, the consuming application should be able to update its GUI from within the event handlers. So, my question is, is there a standard method (independent of any particular GUI framework) for raising events on a different thread??
Any help would be appreciated. Thanks.
You need to use ISyncronizeInvoke. This interface allows you to check if you are on the right thread, and if not, Invoke a method on the correct thread. I haven't done this in WPF, but I assume it is implemented there as well as Windows Forms.
Typically you would just marshal the event data to the main thread by reinvoking the event handler from the main thread. One method is shown below.
private void DispalyMessage(byte[] bytes)
{
if (this.InvokeRequired)
{
lock (_lock)
{
EventHandler d = new EventHandler(DispalyMessage);
this.Invoke(d, new object[] { bytes });
return;
}
}
else
{
//do something with the data
}
}
Enjoy!
You could use SynchronizationContext (which is what BackgroundWorker does, I believe) - or you could just warn your clients that the events will be raised on a background thread, and that they should perform whatever marshalling they need to (as other APIs like FileSystemWatcher do.)
Instead of events from the class library, use a callback method that your GUI code provides. Although the callback will be invoked on the library's thread, your GUI code can decide what's the best way to handle it. This should simplify switching to a different GUI.
Related
I read this excellent article Comparing the Timer Classes in the .NET Framework Class Library and came to the conclusion that anything I could do with Windows.Forms.Timer I can do better with Timers.Timer - and then some.
So the obvious question that comes to mind is: Why is the Windows.Forms Timer offered at all?
Legacy (backward compatibility) support?
Other?
The main convenience of the Windows.Forms.Timer is that its events are fired on the UI (Winforms) thread. If your timer events perform UI operations, it may be the simplest alternative (instead of calling Control.Invoke/BeginInvoke or SynchronizationContext.Post/Send inside all of your events).
The Windows.Forms.Timer events get invoked on the UI thread so you can update the UI from the event handlers directly, which is not normally the case with Timers.Timer (as you would get cross thread access violation exceptions).
And, as #Robert Harvey answered, it also has designer support.
One of advantage of Windows.Forms is that it run in the same thread of GUI and you do not get cross thread exceptions while accessing Form controls.
Windows.Forms.Timer has designer support. So it behaves like any other Winforms component (i.e. you can drag it onto a form, it's part of the Controls collection, etc).
Timer events raised by System.Windows.Forms.Timer class are synchronous with respect to the rest of the code in your Windows Forms app. This means that application code that is executing will never be preempted by an instance of this timer class (assuming you don't call Application.DoEvents). Events fired by the Windows.Forms.Timer class are compatible with your Winform controls; you can safely interact with them without having to call Invoke().
The System.Timers.Timer class is a server-based timer that was designed and optimized for use in multithreaded environments. Instances of this timer class can be safely accessed from multiple threads. Although Invoke() is technically required to interact with Winforms, the Timer class does provide a SynchronizingObject property, to which you can attach the Windows form with which you want to safely interact.
More here:
http://msdn.microsoft.com/en-us/magazine/cc164015.aspx
Well I think the answer is that they are two completely different types of timers. The Windows.Forms.Timer is a single-threaded application timer that's well suited for timers existing on the client running application.
A Timer is used to raise an event at user-defined intervals. This Windows timer is designed for a single-threaded environment where UI threads are used to perform processing. It requires that the user code have a UI message pump available and always operate from the same thread, or marshal the call onto another thread.
In contrast the Timers.Timer is a server-based timer that is better suited for Windows services.
The Timer component is a server-based timer, which allows you to specify a recurring interval at which the Elapsed event is raised in your application. You can then handle this event to provide regular processing. For example, suppose you have a critical server that must be kept running 24 hours a day, 7 days a week. You could create a service that uses a Timer to periodically check the server and ensure that the system is up and running. If the system is not responding, the service could attempt to restart the server or notify an administrator.
You can find their documentation and read the excerpts and more from Microsoft.
It's not that one should never be used or always used, the serve two different purposes.
My belief is that it is for winform designer integration, in that you can drag it onto a form, click it and set its properties in the properties pane.
I am working on a plugin based WPF Application. The plugins are loaded parallely using multiple threads. One of the plugins is a UI plugin that uses a WPF RibbonWindow. I am trying to add a RibbonTab from Plugin A to the UI plugin.
Since the calling thread does not own the RibbonWindow, I am using the Dispatcher.Invoke on the RibbonWindow. Unfortunately the code inside the delegate is never being called. The application is still responsive, but the tab is not being added.
Is there anyway I can access the UI thread from another plugin?
Can I have a thread that can be kept alive all through my application, for me to use that Thread for operating on the RibbonWindow?
System.Threading.ThreadStart start = delegate()
{
log.Debug(Thread.CurrentThread.ManagedThreadId);
if (!this.Dispatcher.CheckAccess())
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate() {
log.Debug(Thread.CurrentThread.ManagedThreadId);
ribbonRoot.Items.Add(myRibbonTab);
});
}
else {
log.Debug("We have access add directly.");
}
};
new Thread(start).Start();
Please let me know if you need any additional information.
Thanks.
You need the Application.Current.Dispatcher to invoke it on the UI thread.
btw: Why are you casting to ThreadStart? (not important, just curious)
If you just want to add the ribbon tab you don't need to start a thread for it (you are already dispatching it to the UI thread) unless there is more you want to do on the thread. Even then it might be better to use the ThreadPool instead of creating a new thread. Any way, in scenarios like this I usually pass the Dispatcher from the main window to the plugin via the plugin interface instead of directly accessing the Application.Current.Dispatcher. Makes it more encapsulated and you have better control over it in unit tests.
I am a bit confused about how GUI can be used in multi-threaded applications.
I hear there is a thing called the UI thread. Which I assume is my main executing thread at the startup of the application.
I also hear (though I am not 100% on this) that doing UI stuff on other (non UI) threads is a very bad idea.
So, if I create a separate thread and I want to call MyForm myForm = new MyForm(); myForm.ShowDialog(); in it, what changes do I need to make for that to be "safe"?
Also, I have had some people tell me that events are spun out on a different thread. (Though I am not sure I believe this.) If they are, then I am confused. I can open a dialog (ie myForm.ShowDialog() in an event and nothing truly horrible happens. (Maybe this depends on if the event delegate was called with Invoke or BeginInvoke?)
Here are a few bits of info that may help you out. What you're saying about working with UI on non UI threads isn't just a bad idea, you'll get an exception. Meaning, if you create a Form in the main thread, and then spawn off a background thread to do some processing and then want to update the Form in that background thread, it'll throw an exception. In your example though, where you create the Form in a background thread, you should be OK. I'd question your design, but it won't blow up AS LONG AS YOU ONLY TOUCH THE UI IN THAT SAME THREAD.
As for events, events handlers are executed on the same thread they were raised on. Meaning, if you have a Form on one thread that spawns off some work on another thread that raises events, but before doing so, you hook into this event on the Form thread, you need to be careful not to touch the UI directly in the event handlers, because those event handlers are being called on the background thread.
Finally, the way to correctly manipulate the UI from a background thread, is by calling Invoke and passing in a delegate that does the UI work you want. HTH
In WinForms you need to call UI-things on UI thread, you always can check on what thread you currents are getting InvokeRequired of UI-control.
void ApplyUiChanges()
{
if(this.InvokeRequired)
{
this.Invoke(new Action(ApplyUiChanges));
return;
}
// UI stuff here...
}
In WPF techinic is alike. But instead of using InvokeRequired you should ask CheckAccess() of DispatcherObject (All UI-controls derive from it)
void ApplyUiChanges()
{
if (!dispatcherObject.CheckAccess())
{
dispatcherObject.Dispatcher.Invoke(DispatcherPriority.Send, new Action(ApplyUiChanges));
return;
}
// UI stuff here...
}
Also you can take a look at Async CTP, which might be useful. But it's only CTP, not a release yet.
Another way to handle UI-thread communication is to use PostSharp. Write (or copy-paste) GuiThreadAttribute. After that, you'll be able to use such semantics:
[GuiThread]
void ApplyUiChanges()
{
// UI stuff here...
}
From what I've experienced, "UI thread" is a misnomer. There isn't one single thread that handles all of the UI for an application. To keep things simple, it's generally a good idea to have UI on one thread, but nothing stops you from spawning another thread, and creating new controls on that thread and showing them to the user. What's important is that control properties are only changed on the thread it was created on. As mentioned by another person, you can see if you are currently on that thread by looking at the Control.InvokeRequired property.
If you are on a thread that isn't the one you want a new form to run on and you don't have the luxury of being on the context of a control that is created on the thread you want, then you'll have to get a reference to the System.Threading.SynchronizationContext of the thread you want it to be on (I usually achieve this by storing a reference of System.Threading.SynchronizationContext.Current from the main thread in a static variable, but this can only be done after at least one control has been created on the thread). This object will allow you to run a delegate on its home thread.
I had to do this once in a Windows application that also hosted a WCF service, and UI needed to be launched from the service, but I wanted it on the same thread as the rest of the UI.
HTH,
Brian
In WinForms applications there is only a single thread which is the UI thread. You don't want to block this thread with long operations so that the UI is always responsive. Also you shouldn't update any UI elements from any thread other than the UI thread.
I always use a BackgroundWorker if I want to perform any lengthy operations from the UI. The major benefit of BackgroundWorker is that it can report progress and report that it is complete via ProgressChanged and RunWorkerCompleted. These 2 events occur in the UI thread thus you can update any UI element safely without the need to use InvokeRequired and Invoke.
I'm having a problem with handling an event on a different thread from where it is raised. The object that is handling the event is not an UI object however, so I can't use Invoke to execute the delegate and automatically switch to the UI thread for event handling.
The situation is as following: I have an MDI application containing multiple forms. Each form has it's own controller class that handles communication between the coupled form and external objects. All forms are either overview or detail forms (e.g. ContactsOverview & ContactDetail) and share the same data.
In the situation where the error occurs the forms appear in a wizard-like sequence, say a detail form is followed by an overview form. In the detail form data used on the following overview form is changed and before switching to the overview form these changes need to be reflected there. An event is raised from the detail form and handled by the controller for the overview form which does the necessary updating of UI elements.
Now the saving of the changed data in the detail form can take a while so it is necessary that the UI remains responsive and other parts of the application can still be used. This is why a backgroundworker is started to handle this. When the data is saved the event is raised on the background thread. The controller for the overview handles this but when the UI needs to be update there are of course cross-thread exceptions.
So what I need is a way to raise the event on the UI thread, but since the handling doesn't happen on a UI element there's no way to switch threads automatically using Invoke.
From searching around the web I've found one possible solution which is using the producer/consumer pattern. But this would require each controller to listen to a queue of events in a separate thread as far as I understand. Since it's an MDI application there could theoretically be any number of forms with controllers and I don't want to be starting up that many threads.
Any suggestions are welcome. If there would be a way to avoid using the backgroundworker alltogether that would be a suitable solution as well.
Thanks for reading,
Kevin
You can use SynchronizationContext, specifically SynchronizationContext.Current, to post messages to the main synchronization context (which is the main thread for a GUI application).
Unfortunately I don't know enough about the class and its usage to say this is a definite solution. In particular, I don't know what you should do if you don't require the main thread to handle your events, but instead a particular thread.
Perhaps the WindowsFormsSynchronizationContext class can help you out, it has a public parameterless constructor, I'm thinking it might associate it with the current thread, so if you construct that object from the thread that owns the controller, and give it to the background thread code, it might work.
You can have an event on the background objec that the UI element subscribes to. In the event handler (of the subscription - so it is part of the window code) you can then to the invocation. This is how I solve this.
You can try this flag but I don't think it's the best idea, just a work around.
You could also try to instantiate the issuing objects in a non-graphical thread, which may fix your problem.
One more thing, can't you have your UI component handle RunWorkerCompleted (with indirections) ?
I'm writting a Windows Forms application in C# that performs a lot of long-running procedures. I need to program the application so that the GUI doesn't lock. What is the best way to program it?
I know how to use the following:
BeginInvoke/EndInvoke
Calling Application.DoEvents() repeatedly (probably not a good idea)
BackgroundWorker
etc.
But how to manage GUI state with call backs, etc... is not trivial. Are there solutions for this (in the form of patterns or libraries)?
Using BackgroundWorker is the simplest way to do what you're trying to do. BackgroundWorker simplifies the logic of dealing with threads, leaving you with very little code you have to write. You just have to handle three events (DoWork, ProgressChanged, and RunWorkerCompleted) and follow a few principles:
Don't ever update the UI inside your long-running method. Have it call ReportProgress instead and handle the ProgressChanged event in the UI logic.
Understand that since the worker isn't running on the UI thread, an exception that your method throws doesn't automatically show up in the UI. It just gets silently written to the console. It's very important to check the Error property of the RunWorkerCompletedEventArgs when the method is done and handle (or throw) the exception. If you don't do this, you won't know that your method failed.
If the method can be cancelled, make sure that it periodically checks the CancellationPending property to see if cancellation has been requested. If it has, once it's done handling the cancellation, set the Cancel property on the DoWorkEventArgs object. Be aware that it's possible for CancellationPending to be true and Cancel to be false; this happens, for instance, when the user requests cancellation and the method finishes before it has a chance to check CancellationPending.
Correspondingly, check Cancel in your RunWorkerCompleted event handler, so that your UI can provide the proper response to what happened while the worker was running.
The examples in the documentation all show the DoWork event handler calling a method of the form. This is almost certainly not what you want to do. Separating business logic from UI is a good idea in general; in background tasks it's essential. If your long-running method is a member of a class that doesn't know that the UI even exists, there's no danger that you'll inadvertently have it call a method that updates a status bar or something.
The Model-View-Controller pattern separates the state of your UI from the visual aspects of the UI. As long as your MVC implementation is thread aware, it should solve the state management issue for you.
This is how I handle multi-threaded UI implementations.
EDIT: Here's a good post on selecting an MVC implementation for WinForms projects.
It is relatively simple to use the ThreadPool to fire off long running processes from the UI. If you want feedback you can use some event handlers to fire on certain events from the long running process, then register for them and update the UI as needed.
MVC is good, but you still need to make sure your process is firing off on a thread other than the UI thread.
All your options are syntactic sugar of doing same thing (Asynchronous execution). May be with different levels of controls. I would go with BackgroundWorker, because your GUI (handled by the main thread) will always be responsive.