Is there an alternative to use the Background Worker in WPF? - c#

I am a beginner with WPF, in my application I need to perform a series of Initialization steps, these take 10-15 seconds to complete during which my UI becomes unresponsive.
I was using yesterday the background worker but it didn't update my window, in fact it was frozen. Not sure, but maybe it didn't work because this control is only for Windows Forms.
UPDATE:
If not too much trouble, can you post me an example to use the alternative? For my case, the program will get some values from a database in a blucle.

Dispatcher.
The Dispatcher maintains a prioritized queue of work items for a specific thread. This might help you for updating your UI. If you have a lot of UI related initializations even this won't be able to help you much.
Dispatcher is not always an alternative to BackgroundWorker actually. The best practice is to select the more appropriate one as per your requirement. For example if you want something to execute without queuing BackgroundWorker is the solution. On the other hand if queuing is not a problem then Dispatcher is an alternative. For example, Dispatcher is using in Spell checkers and syntax highlighting functionality.
WPF Thread Model
All WPF applications start out with two important threads, one for
rendering and one for managing the user interface. The rendering
thread is a hidden thread that runs in the background, so the only
thread that you ordinarily deal with is the UI thread. WPF requires
that most of its objects be tied to the UI thread. This is known as
thread affinity, meaning you can only use a WPF object on the thread
on which it was created. Using it on other threads will cause a
runtime exception to be thrown. Note that the WPF threading model
interoperates well with Win32®-based APIs. This means that WPF can
host or be hosted by any HWND-based API (Windows Forms, Visual Basic®,
MFC, or even Win32).
The thread affinity is handled by the Dispatcher
class, a prioritized message loop for WPF applications. Typically your
WPF projects have a single Dispatcher object (and therefore a single
UI thread) that all user interface work is channeled through.
NOTE :
The main difference between the Dispatcher and other threading methods
is that the Dispatcher is not actually multi-threaded. The Dispatcher
governs the controls, which need a single thread to function properly;
the BeginInvoke method of the Dispatcher queues events for later
execution (depending on priority etc.), but still on the same thread.
See this thread for more information.

You could also queue items up with the thread pool and run the tasks like that, but be careful, if your tasks need to update the UI when they are finished you will have to marshal the data back to the UI thread.

One could use asynchronous delegates.
http://msdn.microsoft.com/en-us/library/ms228963.aspx
Just make sure if you are doing any UI related updates use:
Dispatcher.CheckAccess()
Here a simple example:
private void HandleUIButtons()
{
if (!btnSplit.Dispatcher.CheckAccess())
{
//if here - we are on a different non-UI thread
btnSplit.Dispatcher.BeginInvoke(new Action(HandleUIButtons));
}
else
{
btnSplit.IsEnabled = true; //this is ultimately run on the UI-thread
}
}
Taken from here:
http://blog.clauskonrad.net/2009/03/wpf-invokerequired-dispatchercheckacces.html

Related

How to cilck a button on background thread? [duplicate]

I'm building a WPF application. I'm doing some async communication with the server side, and I use event aggregation with Prism on the client. Both these things results in new threads to be spawned which are not the UI thread. If I attempt to do "WPF operations" on these callback and event handler threads the world will fall apart, which it now has started doing.
First I met problems trying to create some WPF objects in the callback from server. I was told that the thread needed to run in STA mode. Now I'm trying to update some UI data in a Prism event handler, and I'm told that:
The caller cannot access this thread because a different thread owns it.
So; what's the key to getting things right in WPF? I've read up on the WPF Dispatcher in this MSDN post. I'm starting to get it, but I'm no wizard yet.
Is the key to always use Dispatcher.Invoke when I need to run something which I'm not sure will be called on the UI thread?
Does it matter if it actually was called on the UI thread, and I do Dispatcher.Invoke anyway?
Dispatcher.Invoke = synchronously. Dispathcher.BeginInvoke = async?
Will Dispatcher.Invoke request the UI thread, and then stop to wait for it? Is it bad practice and risk of less responsive programs?
How do I get the dispatcher anyway? Will Dispatcher.CurrentDispatcher always give me the dispatcher representing the UI thread?
Will there exist more than one Dispatcher, or is "Dispatcher" basically the same as the UI thread for the application?
And what's the deal with the BackgroundWorker? When do I use this instead? I assume this is always async?
Will everything that runs on the UI thread (by being Invoked) be run in STA apartment mode? I.e. if I have something that requires to be run in STA mode - will Dispatcher.Invoke be sufficient?
Anyone wanna clearify things for me? Any related recommendations, etc? Thanks!
Going over each of your questions, one by one:
Not quite; you should only invoke onto the UI thread when necessary. See #2.
Yes, it does matter. You should not just automatically Invoke everything. The key is to only invoke onto the UI thread if necessary. To do this, you can use the Dispatcher.CheckAccess method.
That is correct.
Also correct, and yes, you do run the risk of less responsive programs. Most of the time, you are not going to be looking at a severe performance hit (we're talking about milliseconds for a context switch), but you should only Invoke if necessary. That being said, at some points it is unavoidable, so no, I would not say it is bad practice at all. It is just one solution to a problem that you will encounter every now and then.
In every case I have seen, I have made due with Dispatcher.CurrentDispatcher. For complex scenarios, this may not be sufficient, but I (personally) have not seen them.
Not entirely correct, but this line of thinking will not do any harm. Let me put it this way: the Dispatcher can be used to gain access to the UI thread for the application. But it is not in and of itself the UI thread.
BackgroundWorker is generally used when you have a time-consuming operation and want to maintain a responsive UI while running that operation in the background. Normally you do not use BackgroundWorker instead of Invoke, rather, you use BackgroundWorker in conjunction with Invoke. That is, if you need to update some UI object in your BackgroundWorker, you can Invoke onto the UI thread, perform the update, and then return to the original operation.
Yes. The UI thread of a WPF application, by definition, must be running in a single-threaded apartment.
There's a lot to be said about BackgroundWorker, I'm sure many questions are already devoted to it, so I won't go into too much depth. If you're curious, check out the MSDN page for BackgroundWorker class.

WPF UI on multiple threads?

I have a large WPF MVVM application (over 100 windows currently and growing.) Although I try to do everything I can on background threads there always comes a time the results must be sent back to the UI thread to be displayed. When you have many windows doing this at the same time it can effect performance.
I've tried to run each window on a separate UI thread in the past but ran into so many threading issues I had to revert back to WPF's default model of only 1 UI thread per app.
I know with windows 10 coming many users will open even more windows on separate desktops and thus make this worse.
Anyone know how to get multiple UI threads to work correctly in WPF? Or have any info I can investigate to help get my app further down this road?
I approach I tried in the past was to do something similar to this:
private void OnCreateNewWindow(
object sender,
RoutedEventArgs e)
{
Thread thread = new Thread(() =>
{
Window1 w = new Window1();
w.Show();
w.Closed += (sender2, e2) =>
w.Dispatcher.InvokeShutdown();
System.Windows.Threading.Dispatcher.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
This was about 2 years ago and I can no longer recall all the issues I faced using this unfortunately.
Is there another way? Has anyone gotten an app with many windows to work correctly using this approach or another?
In general, it "works". The main thing you have to do is set the thread to STA (as in your example). But you gain little or nothing by running some of the UI in a different thread. Each thread can still be blocked by long-running tasks, so you still need to execute those in yet another thread, and you still have the cross-thread issue requiring some kind of marshaling back to the UI thread (e.g. Dispatcher.Invoke()).
Furthermore, with more than one UI thread, now not only do you have to keep track of which UI thread goes with which UI object (since they still can be used only with the thread that owns them), you will have more problems with UI objects interacting with each other, because those owned by different threads are mutually exclusive. Each is required to be accessed only in the thread in which it's owned, so the only way to have them work together is to create some kind of proxy system to pass data and events back and forth between threads.
Basically, it never was and still is not a good idea to create more than one thread for the UI.
Fortunately, as of .NET 4.5 and C# 5.0, there are framework and language features that greatly simplify the handling of background operations and the marshaling of information back to the UI thread. With the async/await feature, you can initiate asynchronous operations with framework features like the Task<T> class or certain class methods (usually with names ending in the word Async), have the UI thread unblocked for the duration of the operation, and yet easily write code to handle whatever work has to be done at the end of the operation.
There is also the Progress<T> class, which implements the IProgress<T> interface in a way that is convenient for dealing with UI progress updates, i.e. invokes the callback on the UI thread (as long as you create the Progress<T> instance in the UI thread, of course).
So, take the path that .NET and C# are encouraging you to take, and avoid the one that is hard. Keep all your UI in a single thread, and solve whatever issues come up using the tools provided instead of trying to fight the API. :)

Custom tracelistener freezing GUI in WPF application

Completely rewrote the question as I now have more information about what is happening.
I have a customtracelistener which overrides the writeline method to add strings to a custom observablecollection. This collection class dispatches all notification events to the UI thread to allow other threads to update it, and still allow WPF data binding.
I have a usercontrol which includes a listbox. The listbox binds the observablecollection in the trace listener to it's itemssource.
In my application startup, I set up the windows/usercontrols/viewmodels, and show the window. I then kick off a worker thread that runs some backend processes required for the app. If the background threads do a Trace.WriteLine before the UI thread has completed all the user control setup and databinding, my application deadlocks.
I've been able to somewhat reasonably prove this race condition by adding sleeps and other random long running tasks in the UI thread and/or delaying starting the worker thread to give the UI thread time to complete.
The solution I'm thinking of implementing now is creating a AppSetupCompleted method which kicks off the worker threads for all the backend processes, and sending this to the Dispatcher with a Background priority. In theory, should this delay the worker threads until all of the bindings for the WPF controls and viewmodels have been setup successfully?
sounds like a deadlock or livelock to me... assuming deadlock (low cpu when app freezes), attach a debugger to the application and break it. Look at the call stack of the threads (UI and the one you called Trace.WriteLine from) to see where they are locking.
If you can't figure out that is blocking, add the call stacks to your question, it may help us answer your question.

UI freezing problem in c# 2.0

Sometimes I saw that when I call a method from my form to do something that my UI freezes. How to solve this problem? If I call that method in separate thread then problem will be solved?
If I call method in separate thread like the code below
new System.Threading.Thread(delegate()
{
HeavyMethod();
}).Start();
does this solve my problem or is there any better solution?
Call the method on a Background Worker would be the best solution.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Doing that you can control when things get updated (using the Report Progress Feature) and allow you to cancel the work.
Also, make sure that whatever resources you manipulate in the backgroundWorker1.RunWorkerAsync(); are properly shared. You can get into what is called "Race Conditions" which causes your output to be non-determanistic (e.g. you won't get the same results every time you run the method)
For a good walk through on Multithreading and shared resources, see this link:
http://www.c-sharpcorner.com/uploadfile/mgold/multithreadingintro10062005000439am/multithreadingintro.aspx?articleid=920ecafc-e83b-4a9c-a64d-0b39ad885705
If you are calling your method in response to an event, then by default the method will be running on the GUI thread (the thread that the runtime uses to handle all user events). If that method is huge and/or heavy, then it will "freeze" the UI as you describe.
Making it run on a separate thread is a viable solution for many of these cases.
There are cases, however, when you'll actually want the UI to "block" (for example, if you are updating a lot of controls, you don't want the user to mess with them in the meanwhile). For such cases, the sanest approach is to pop up a modal "wait" dialog.
Since it is C# 2.0, I suppose it is WinForms. Don't hold up the UI thread with CPU-bound code.
You can spawn a new thread to run your CPU-bound code, but you have to be careful not to access WinForms controls, especially not to update control properties. Many WinForms controls can only be accessed/updated from the UI thread. Check the InvokeRequired field to see if you need to marshal (i.e. use Invoke) the call from another thread back to the UI thread.
Also consider using the ThreadPool instead of creating a new thread.
That is correct, If you move the heavy processing off of the UI Thread then it should free up the UI to redraw. For what you want to do your implementation should work just fine. Although ThreadPooling or BackgroundWorker would be the suggested implementations (http://msdn.microsoft.com/en-us/library/system.threading.threadpool(v=VS.80).aspx), (http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx).

Threads, events and the GUI

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.

Categories