UI thread vs. BackGroundWorker thread - wpf

Im reading a WPF book and I see this code:
private void bgw1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
int percenti;
percenti = e.ProgressPercentage;
progressBar1.Value = percenti;
}
The question is simple.
if
ProgressBar belongs to UI Thread and
BackGroundWorker works with a Background Thread
Why are there no errors (like: The calling thread cannot access this object because a different thread owns it.)?
thanks.

Why are there no errors (like: The calling thread cannot access this object because a different thread owns it.)?
This is one of the main advantages to using BackgroundWorker. The BackgroundWorker component automatically marshals calls for progress and completion back to the synchronization context (thread) that starts the job.
In this case, that means that the event handlers for ProgressChanged (and the completion event) happen on the WPF UI thread.

The BackgroundWorker handles the thread context switch for you. The event BackgroundWorker.ProgressChanged will be raised on the UI-Thread and hence your callback bgw1_ProgressChanged will be called in the context of the UI-Thread.
This was the main purpose for the BackgroundWorker's existence: To make async work easy and straight forward in conjunction with a UI.
BackgroundWorker exists since .NET 1.0. Now that we live in 2012, we have the Task class and the Task Parallel Library and soon the c# async keyword as general means for everything async, wich makes the BackgroundWorker kind of obsolete or at least old school.

It is because you cannot make changes in the Do_work method of the background worker.
progress_changed event keeps updating what is happening in the other thread.
Bes to clear your concept through this link-->
[https://www.codeproject.com/Articles/99143/BackgroundWorker-Class-Sample-for-Beginners][1]

Related

Convert a WPF dispatcher to Winforms BGworker?

i recently acquired some source code for a console wrapper for a server. The program was originaly in WPF and part of the code was:
private void ServerProc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
ConsoleTextBlock.Text += e.Data + "\r\n";
ConsoleScroll.ScrollToEnd();
}));
}
private void ServerProc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
ConsoleTextBlock.Text += e.Data + "\r\n";
ConsoleScroll.ScrollToEnd();
ParseServerInput(e.Data);
}));
}
Its also had this annotation in both voids:
// You have to do this through the Dispatcher because this method is
called by a different Thread
However in WinForms there is no such thing - is there a way to change this to a Background worker or something (Ive barely done any multi-threading)?
Both methods are event handlers. Chances are they are from some kind of listening code and I would expect that they are called from a non UI thread (eg normally a threadpool thread that is doing the listening). You can check that by putting a break point and looking at the threads window in the debugger.
So you will need to apply the winforms way of updating the UI from a non UI thread.
If you search SO you should find quite a lot on how to do that. E.g
Updating UI from a different thread
How to update GUI from another thread in C#?
Some background: A process that is running in a thread other than the UI thread is not allowed to access any UI controls directly. Your WPF ServerProc is running in a different thread than your UI which requires the Dispatcher to help you communicate from the ServerProc thread back to the UI controls in your UI thread.
If your ServerProc -- in WPF or WinForms -- were running in the UI thread, you would not need to surround it with the Dispatcher.Invoke call.
For you, you can put your ServerProc in a BackgroundWorker (MSDN example). Your DoWork method would contain the meat of the code doing the work and then depending on how the ServerProc does its work, you might be able to use ProgressChanged to do what both your sample WPF methods are doing. ProgressChanged has a parameter passed in that you would indicate if it were an error or data has been received and inside the function you could display the appropriate info. Take a look at the MSDN docs because they have a good example.
What's important to point out is that ProgressChanged happens on the UI thread so you do NOT need to surround your calls to your UI controls with Invoke; just call them normally. Same goes for RunWorkerCompleted which may be the other option for displaying data when your ServerProc has finished its job.
Finally, if you actually had to access a UI control from within your thread, you do something very similar looking as your WPF code sample. Look at MethodInvoker. Instead of Dispatcher, you're really just calling it from your main Form.

Application Dispatcher and Control Dispatcher

Assume i have control button with name "button1" and function with name "doSomething". Function "doSomething" is called from another thread.
i have two method to call function doSomething from UI thread.
First, from control button dispatcher
this.button1.Dispatcher.BeginInvoke(new Action(() => { doSomething(); }));
and Second, from application dispatcher
this.Dispatcher.BeginInvoke(new Action(() => { doSomething(); }));
The result is same, what is the real different ?
The same dispatcher instance is referenced in all controls owned by the same thread. There is no difference.
All of UI controls (which were created normally), share the same dispatcher instance. That dispatcher is working on UI thread. If you create some control on backgroud thread, it will create new dispatcher on that thread, and this will not be very good.
The best way to avoid most problems with threading and UI controls both in WinForms and WPF is to use System.Threading.SynchronizationContext.Current. The workflow is simple: you get System.Threading.SynchronizationContext.Current while you are on UI thread and save it somewhere (for example in a public static field). Then, whenever you want to run some code on UI thread, you access that persisted SynchronizationContext intance and use its Send or Post methods. It will run you delegates on thread, where SynchronizationContext was achieved (for current case on UI thread). Also it is smart enough, to use the current way of Invoking (message loop for WinForms and dispatcher for WPF) and also if you are already calling from UI thread it will just run your delegate synchronously.
Just keep in mind, that you should get SynchronizationContext only after you create your first control on the current UI thread, because SynchronizationContext will be initialized right after that.
In most of the case, We have single UI thread. So, It doesn't make difference you call
control.Dispatcher(which comes inherited from DispatcherObject parent of the controls).
or
Disptacher.Current.
But there are scenarios, where you will end up having multiple dispatchers.
So, in that situation, Control.Dispatcher will help as It will find out the current dispatcher to respect Thread Affinity. In this Dispatcher.Current won't help.
One scenario, having dedicated thread(with dispatcher) for displaying busy indicator as default UI thread is busy in rendering large list of controls.
However, with SynchronizationContext is another way to avoid such issues. but what if that context or thread is no longer required or it has been set to null by any other developer. So, It is always wise to go for Control.Dispatcher in my opinion.

The calling thread cannot access this object because a different thread owns it

I have a WPF window in the main thread. On button clock of this window i am loading the data. Meanwhile i am using a seperate thread to display a wait screen. But i am not able to set the main window as the parent of the wait screen. It throws following error:
The calling thread cannot access this object because a different thread owns it
You want to look into the Dispatcher.Invoke method.
You could use the BackgroundWorker class to perform your asynchronous operations; it should take care of any thread affinity issues you might be having. It's as simple to use as wiring up a couple of events.
This should get you started.
Alternatively you can use Dispatcher.Invoke to perform the operation on the correct thread:
private void DoStuffOnThread()
{
Dispatcher.Invoke(new Action(DoStuffOnUIThread));
}
private void DoStuffOnUIThread()
{
// ...
}
The problem you are running into is that windows/controls have thread affinity (they are "owned" by a particular thread), and you cannot mix them between threads.
If you want the wait screen's parent to be the main window, you should create the wait screen on the main window's thread. Then, on the other thread, you can tell the wait screen to display by using Invoke.
There is a good article on cross-thread operations in WPF here (search down for Figure 4 Updating the UI):
http://msdn.microsoft.com/en-us/magazine/cc163328.aspx

WPF: Is there a simple way to create a Progress Window?

I tried creating one, but the BackgroundWorker in Window1 couldn't access the ProgressBar in Window2 once the reportProgress was activated, because "The calling thread cannot access this object because a different thread owns it".
Seems there's a lower level thread model I could use, but it also seems a lot more complicated.
You just need to get the ProgressBar disptacher.
You can access the ProgressBar with:
Window2.prograssbar.Dispatcher.Invoke(
() => /*the code for modifying the progressbar*/ );
In WPF, UI controls and properties may only be activated from the UI thread. In order to change the progress bar's value from a different thread, you can add a command to the GUI thread's dispatcher queue. You can do this by passing a delegate to the Dispatcher.Invoke() method. See the article at http://msdn.microsoft.com/en-us/magazine/cc163328.aspx for more details.
You need to look into Delegates

How to ensure that a winform closes in exactly X seconds

In my WinForms application, I need to pop up a little custom dialog that stays on the screen for X amount of seconds and then disappears. So I use a System.Threading.Timer to invoke the _dialog.Close() method once the appropriate amount of time has elapsed. This of course means that I have to do the whole "if InvokeRequired BeginInvoke" dance which isn't really a problem.
What is a problem however is that my main thread might be off doing god knows what by the time the BeginInvoke is called. It might not get around to closing the window for quite a while. I don't need the window to close at a millisecond's notice, but within a second or so is really necessary.
So my question is how does BeginInvoke actually work itself into the main thread and how can I get around this odd limitation?
If your UI thread is busy for many seconds at a time, then:
You won't be able to close a window associated with that UI thread, without peppering your code with Application.DoEvents calls (a bad idea)
Your whole UI will be unresponsive during this time. The user won't be able to move any of the application's windows, and if the user drags other windows over the top of it and off again, you'll end up with an ugly mess while the UI waits to repaint itself.
Certainly use a System.Windows.Forms.Timer instead of a System.Threading.Timer for simplicity, but more urgently, look at fixing your code to avoid having such a busy UI thread.
UPDATE: The conclusion would seem to be that utilising ['BackgroundWorker](http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx) along with a System.Windows.Forms.Timer would be the best approach.
Best to use System.Windows.Forms.Timer for this purpose - this is precisely the sort of application it was designed for. Add one to the pop up form and start it as soon as the form is shown, then hide the form on the Tick event. This solution won't give you any threading issues because the timer runs purely on the UI thread.
Edit: If you want to move the logic outside of your popup form, then I recommend you just create an overload for the Show method within the form code that takes a timespan for its parameter and does the job of setting the Timers's interval and starting it.
Edit 2: If you're main (UI) thread is doing too much work and therefore blocking the message pump and not allowing the timer to fire, then it's the design that's the issue I'm afraid. Your UI thread should never be blocking for more than a fraction of a second. If you need to do serious work, do it in the background using a worker thread. In this case, because you are using WinForms, BackgroundWorker is probably the best option.
Create a dedicated thread and use Application.Run to create and show your form. This will start up a message pump on the second thread which is independent of the main thread. This can then close exactly when you want it, even if the main thread is blocked for any reason.
Invoke and BeginInvoke do get into the main thread by using a window message posted into that thread, waiting for it to be processed. Therefore, if the message pump of the main thread is not processing messages (e.g. busy), it will have to wait. You can mitigate this factor by calling Application.DoEvents() when doing time-consuming operations in the main thread, but that's not really a solution to the problem.
Edit: Sample from some splash screen code (the form requires no special code or logic):
private void ShowSplashInSeparateMessageQueue() {
Thread splash = new Thread(ShowSplashForm);
splash.IsBackground = true;
splash.Start();
}
private void ShowSplashForm() { // runs in a separate thread and message queue
using (SplashForm splashForm = new SplashForm()) {
splashForm.Load += AddDestroyTimer;
Application.Run(splashForm);
}
}
private void AddDestroyTimer(object sender, EventArgs e) {
Form form = (Form)sender;
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(form.Container);
timer.Tick += delegate { form.Close(); };
timer.Interval = 5000;
timer.Start();
}
Invoke just places the delegate into the message queue of the thread you want to invoke it on. You could use the Dispatcher class to insert the delegate with a high priority, but there is no gurante that this will meet you timing constraints if the thread is doing a lot of work.
But this might be an indication that you are doing to much work on the user interface thread. Not responding for a second is a pain to a user. So you might think about moving some work out of the user interface thread.

Resources