I have read about this: "The UI thread queues work items inside an object called a Dispatcher. The Dispatcher selects work items on a priority basis and runs each one to completion." https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/threading-model?view=netframeworkdesktop-4.8
Does work items include control events ?
Yes, the control events, such as for example Button.Clicked, are raised synchronously on the UI/dispatcher thread.
Related
I have implemented a WPF application using background worker in which I am assigning data from database to combobox.
I have used observable collection as ItemSource for combobox .
When I try to fill up the observable collection in DoWork method of background worker, UI is not getting updated but if I move same code to ProgressChanged or RunWorkerCompleted then it is working fine.
I want to know why the DoWork method is not updating the UI.Also the logic for updating UI should be in ProgressChanged or RunWorkerCompleted?
To quote MSDN : "You must be careful not to manipulate any user-interface objects in your DoWork event handler" - so in your DoWork method call ReportProgress event and update your ui in the ProgressChanged event handler
There are many online examples showing how to correctly utilise a BackgroundWorker. As you haven't bothered to show us your code, all we can do is guess, but I'm guessing that you simply haven't implemented your code properly. Not wanting to duplicate this code once again, I'd rather advise you to take a look at my answer to the Progress Bar update from Background worker stalling question here on Stack Overflow.
It clearly demonstrates how to implement a BackgroundWorker correctly.
I have some UI task which took to long. I have some 'home made' property grid ( I uses an ItemControl , where item template uses a ContentControl, the item itself holds the datatemplate to be used in the Content control.).
The application is Shapes viewer, where each shape has its properties. each time the user clicks on some shape, the property grid shows its properties (60 different properties).
The updates process takes something about 1-2 sec. while this updating the application freeze.
Is there any way to do the updating of the property grid in the background?
Is there any way to stop last updating?
Regards, Leon
You should implement the MVVM pattern to make sure that your UI controls is a way to DISPLAY your data rather than be the HOLDER of data.
You can then choose to do various background tasks and only update VM content when ready.
Check out this video:
http://blog.lab49.com/archives/2650
you need to work with thread and dispatcher to do this.
Dispatcher in WPF/SL - http://www.switchonthecode.com/tutorials/working-with-the-wpf-dispatcher
In order to use another thread you have some options:
Threadpool (TaskClass only On .Net 4) - http://msdn.microsoft.com/en-us/library/3dasc8as(v=vs.80).aspx
Thread class - http://msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx
BackgroundWorker Class - http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx
The 3rd option is the easiest if you don't know how to work with threads.
I guess what taking so long is the fetching the properties so what you need to do is to perform the fetch in another thread and then to use Dispatcher in this thread to update your datagrid,
you have to use Dispatcher to update your GUI from another thread.
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.
I have scenario where thread updates form's control. I followed http://msdn.microsoft.com/en-us/library/ms171728.aspx to make it work, but I was not successful.
Program creates form control(list view), and a thread to fetch information from internet(stock quotes). Whenever user selects a known symbol from other form control, that would be added in listView, this intern adds to thread to fetch quotes from internet, and a delegate would be added to for that specific symbol, thread iterates through all the watch list symbols to fetch quotes from internet whenever there is change in price, thread calls registered delegate. In that delegate I am accessing listView elements, here I am facing problems thread inconsistent issues.
To solve this problem I followed the above mentioned link,
Approach-1) In the delegate I started background worker. Same problem
Approach-2) Main program creates background worker, this worker loops around a list to update in listView. Delegate adds new updated price to list on which background worker is looping. When background worker is accessing listView again thread inconsistent problems arise.
How to resolve this problem?
When background worker is accessing listView again thread inconsistent problems arise.
Yes. This is because it shouldn't be done. A Background Worker only provides safe access to the UI the RunWorkerCompleted and ProgressChanged events. The DoWork event is still run in the non-UI thread. To access the UI from the non-UI thread, "marshal back" to the UI-thread using Control.Invoke or SynchronizationContext.Send (these should lead to further findings if used as keywords.)
Happy coding.
I have a ListBox bound to an ObservableCollection. The items in the collection each signify a different step with a method to perform that step. What I would like to do is have a BackgroundWorker loop through the collection, run each item's action method, and have the current step be reflected by the ListBox.
My first iteration used no threading and was just to get the step running going. Now I have created a ListCollectionView, set it to represent the data in the ObservableCollection, and have bound the ListBox's ItemsSource to it instead of the ObservableCollection. I noticed running through the steps still blocks the UI thread's updates even though I'm explicitly incrementing the CurrentItem.
I want to use the ListCollectionView inside a BackgroundWorker but most examples I'm finding are written assuming you are modifying the contents or sorting of the list. I don't wish to do this; I simply want to increment the CurrentItem for each iteration. I'm guessing simply referencing it won't get me very far as it is tied to items on the UI thread and the compiler will complain. Any thoughts or pointers would be much appreciated.
You shouldn't be seeing any complaints from the compiler, but you will be getting exceptions at runtime if you try to update anything that fires an INotifyPropertyChanged PropertyChange from the background thread. There are a few ways around this. You can use Dispatcher.Current.Invoke to just do updates from inside your DoWork method. You can try to rig something through a ProgressChanged handler (runs on the calling thread) and calls to ReportProgress for each completed step. Or you could do the updates in the RunWorkerCompleted handler (also runs on calling thread) and maybe use a series of consecutive BackgroundWorker calls that are triggered from the previous one's completed handler (this can get messy if you don't manage the steps through a generic queue or something similar).
You need to check out WPF Cross-Thread Collection Binding – Part 4 – The Grand Solution and the source I think is on QuantumBitDesigns.Core
This allows you to update a list from another thread and have the changes automaticaly reflected on a bindable observable collection.
Figure: The demo app shows multiple updates to a single ObservableCollection
I have used this on multiple projects with fantastic results.