WPF element bound to observablecollection updated on worker thread - wpf

I have been dealing with multithreading issues for a while now. In the past few days I have been trying to ensure all my calls are thread safe. I have just run into an issue that has thrown me. Here is the scenario:
I am attempting to plot a waveform, using an Infragistics XamDataChart control, which is passed ~500 points/sec/waveform. Upon launch of the application I create objects that have an ObservableCollection property called WaveData and these properties are bound directly to the xaml in an itemscontrol. When the data comes in it is stored in a Queue and a spawned worker thread is used to dequeue the data and update the collection at the appropriate position.
Spawn worker thread:
QueueProcessThread = Task.Factory.StartNew(() => UpdateWaveFormCollections(WaveForms), tokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
Code to update the collection which runs in a loop (some lines of code omitted for brevity):
waveForm.LastDisplayedTimeStamp = DateTime.Now; // move the last displayed time up
int collectionSize = waveForm.WaveData.Count;
while (waveForm.WaveDataBuffer.Count > 0 && waveForm.WaveDataBuffer.Peek().TimeStamp < waveForm.LastDisplayedTimeStamp)
{
if (waveForm.CurrentPosition >= collectionSize)
{
waveForm.CurrentPosition = 0;
}
waveForm.WaveData[waveForm.CurrentPosition] = waveForm.WaveDataBuffer.Dequeue();
waveForm.CurrentPosition++;
}
As you can see, I do not actually add/remove items to/from the collection but instead just update the item at a specific position. This is because I wanted it to look like a patient monitor at a hospital.
The problem I am running into is that I realized that I am updating this collection on a non UI thread and that collection is bound to the Infragistics LineSeries directly...and this is working. However, another graph using an Infragistics StepLineSeries throws an exception when I update that collection on a non UI thread which is expected. How is it possible that I am able to update a bound collection on a non UI thread? I am concerned by this because 1) occasionally I do get an error that a collection cannot be updated on a non UI thread and 2) when I switched the waveform update to be on the UI thread via a dispatcher the performance was so bad the GUI was unusable. I need to understand why this works so I know how to proceed. I do not want to deploy an application that might fail at any time due to thread mismanagement on my part. I am looking for possible reasons why/how it might be possible to update a bound ObservableCollection on a non UI thread. Any help/suggestions would be appreciated.

Maybe you need to look into using the Dispatcher (unless thats part of your code omitted).
You can use the Dispatcher method when you do an operation that will require code to be executed on the UI thread.
Maybe you could retrieve that data in the background worker thread and when you update your collection propagate changes back to the UI thread
e.g.
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
new Action(() => methodHere = 50));

Try using dispatcher invoke to make sure the collection will be accessed through UI thread, thus not allowing any other events to fire on a non UI thread.
Application.Current.Dispatcher.BeginInvoke(new Action(()=>
{
// code here to access collection
}));

The answer I was looking for is that you can update properties of a databound object and WPF will take care of the dispatching for you, however, you cannot update collections (add/remove/clear) from a non UI thread. In my waveform I was not adding points but updating the value of the item at a specific index. However, in the other scenario I was always adding and removing points.

Related

Read .TXT into ListBox in realtime

I am reading a large Txt document into a WPF app for some serious swap/replacemnt operations. The files are actually 3D STP models so they are fairly large, but im working with them as raw text for this project. The files are read into List to avoid having to open them multiple times, and to make comparisons easier.
Anyway, I'm trying to get the listbox to scroll dynamically as lines are added to it, ala a console window so the user can see that something is happening since calculations can take a bit of time depending on filesize. I also added a progress bar to count away as the total line number is read through.
Neither my progress bar, nor ListBox seem to update as work progresses though. The final output simply lands in the listbox completed, and the progress bar goes from 0-max at the same time.
This is the gist of what I am doing, which is fairly simple:
foreach (string Line in OriginalSTPFile.Lines)
{
string NewLine = EvaluateString(Line); //string the modified to whatever here
pBar.Value++; //increment progressbar
OutputWindow.Items.Add(NewLine); //add line to the ListBox
}
I just want the listbox an progress bar to update in realtime as progress changes. I tried using:
Dispatcher.BeginInvoke(new Action(() => OutputWindow.Items.Add(NewLine));
But got the same results. Do I need a more elaborate method of multithreading here? I assumed the first method would've worked since I wasn't generating any cross-thread exceptions either.
This article will give you all the code that you need.
Backgroundworker with Progressbar
It describes very well what to do and which elements to use.
Dispatcher.BeginInvoke signals to invoke a method on the Dispatcher's thread. However, that's essentially like a post message, as it won't occur while the main thread is locked up doing work. And until the main thread is available again, it won't update the UI visually, even if you change values.
You'll need to perform the work in a background thread.
But to update the UI, you'll have to do so on the UI's main thread. This is a limitation of WPF. This is why you were directed to Dispatcher. I'm guessing someone assumed your work was already on a background thread.
To create a thread, you use Thread.Start passing it a delegate to perform. If you use a anonymous delegate or a lambda, you can refer to variables on the stack, but be aware that they will persist until the delegate quits. This is why you cannot use reference variables in a anonymous delegate.
Backgroundworker is a special type of background thread. It automates some of the expectations of a worker thread (notifying of completion, and updating on progress), but you can achieve the same results without it.
To update the UI during the thread's process, you'll need for that thread to be able to access the main UI thread. You can do that by passing it a dispatcher, referring to a dispatcher from outside the anonymous delegate, or by an object that contains a dispatcher. You can always read values from any object on any thread, so accessing the dispatcher by UIElement on another thread is fine.
To update the UI, you'll call Dispatcher.BeginInvoke with a delegate that entails the work to perform.
Here's psuedo-code of the overall scheme
class TestProgress
{
ProgressBar _ProgressBar;
void DoWork()
{
var worker = (Action)(() =>
{
int progress = 0;
// do stuff, delta is change in progress
progress += delta;
_ProgressBar.Dispatcher.BeginInvoke((Action)(() =>
{
_ProgressBar.Value = progress;
}));
});
Thread.Start(worker);
}
}

UI update after background operation blocks binding on ObservableCollection

I have this:
Shows a waiting animation to 'block' the UI while performs a loading operation in the background.
At the end of the loading I call a method that instances a User Control and displays some data by using Bindings (and ObservableCollection among others)
This User Control gets displayed and user can interact with it, however the ObservableCollection seems to be stuck in another thread as it doesn't allow to add new items to it.
I've tried to update the UI at the Completed event of a BackgroundWorker, using Dispatcher, using DispatchTimer... all of this displays the User Control, but the ObservableCollection stays of out reach for adding.
The code that tries to add items to the collection is inside the UserControl.
The exact error is: "This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread"
This does not happen if I don't do the loading in the background.
Thank you for any workaround for this.
By the way, trying to add the items using Dispatcher doesn't work either.
In other words, what I would like to do is to create an object in the UI Thread while being in the background... I know this may sounds silly.
You may have to check which Dispatcher you are using? In your case you could be referring to two different dispatchers.
Also why not use thread safe observable collection?
Usually I will create the objects on my UI thread, then populate them with data obtained from a background thread.
For example,
void async LoadButton_Clicked(object sender, EventArgs e)
{
MyCollection = new ObservableCollection<SomeItem>();
// Can also use a BackgroundWorker
var collectionData = await GetCollectionData();
foreach(var item in collectionData)
{
MyCollection.Add(item);
}
}
I'm using C# 5.0 async and await keywords for asynchronous operations, but you can also use a BackgroundWorker that does your background work.
You can also use Dispatcher.BeginInvoke() for some lighter background work (such as copying data into MyCollection), although for heavy work I find it still locks up the UI so I prefer to use background threads.
It is not possible to modify the contents of an ObservableCollection on a separate thread if a view is bound to this collection, instead you can override ObservableCollection and provide support for it and use it across your application.
This sample contains exactly what you want - http://tomlev2.wordpress.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/
When it comes to threads and ui-elements one of the most important rules to follow which may safe you a lot of trouble in the long run is to keep ui-element instantiation on the ui-thread. Surely you can manage that. And if you need to change those objects from another thread you can use the Dispatcher.
(The threading model reference may also be of interest)
Thank you everyone for your help... a guy from MS visited the company (sorry for the commercial annotation) to do other things, I stoled him and show this behavior. In a matter of 2 minutes founds the source of the problem... which I'm not sure to really understand.
It happens that I'm using an ICollectionView to display a sorted/filtered version of my problematic ObservableCollection. I was creating this ICollectionView in the constructor of my class, so at the moment of deserialization it was created in another thread. He suggested to move this creation to a further time in code (when the related property gets read). This solved the problem.
However the ObservableCollection, created in that other thread, now lets me add new item. Not sure why, but now it works.
Sorry for being this late and thank you again.

How would I loop through a collection in a separate thread and reflect the current item on the bound ListBox?

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.

Creating WPF components in background thread

Im working on a reporting system, a series of DocumentPage are to be created through a DocumentPaginator. These documents include a number of WPF components that are to be instantiated so the paginator includes the correct things when later sent to the XpsDocumentWriter (which in turn is sent to the actual printer).
My problem now is that the DocumentPage instances take quite a while to create (enough for Windows to mark the application as frozen) so I tried to create them in a background thread, which is problematic since WPF expects the attributes on them to be set from the GUI thread. I would also like to have a progress bar showing up, indicating how many pages have been created so far. Thus, it looks like Im trying to get two things to happen in parallell on the GUI.
The problem is hard to explain and Im really not sure how to tackle it. In short:
Create a series of DocumentPage's.
These include WPF components
These are to be created on a background thread, or use some other trick so the application isnt frozen.
After each page is created, a WPF ProgressBar should be updated.
If there is no decent way to do this, alternate solutions and approaches are more than welcome.
You should be able to run the paginator in a background thread as long as the thread is STA.
After you've set up your thread, try this prior to running it.
thread.SetApartmentState(ApartmentState.STA);
If you really must be on the GUI thread, then check out the Freezable class, as you might have to move the objects from your background thread to the GUI thread.
If the portions that require the UI thread are relatively small, you can use the Dispatcher to perform those operations without blocking the UI. There's overhead associated with this, but it may allow the bulk of the calculations to occur in the background and will interleave the work on the UI thread with other UI tasks. You can update the progress bar with the Dispatcher as well.
My guess is that everything that is time-consuming to create is within your Visual. If so, there is an easy solution: Don't create actual DocumentPage objects and their associated Visuals until DocumentPaginator.GetPage() is called.
As long as the code that consumes your document only requests one or two pages at a time there will be no performance bottleneck.
If you're printing to the printer or to a file, everything can be done on a background thread, but if you're displaying onscreen you only need to display a few DocumentPages at a time anyway. In either case you won't get any UI lockups.
The worst case scenario would be an app that displays pages in a thumbnail view. In this case, I would:
The thumbnail view would bind its ItemsSource to a "RealizedPages" collection which initially is filled with dummy pages
Whenever a dummy page is measured, it queues a dispatcher operation at DispatcherPriority.Background to call DocumentPaginator.GetPage() and then replace the dummy page in the RealizedPages collection with the real page.
If there are performance concerns even with realizing a single page because of the number of separate items, this same general approach can be used within whatever ItemsControl on the page has the large number of items.
One more note: The XPS printing system doesn't ever process more than one DocumentPage at a time, so if you know that's your client you can actually just keep returning the same DocumentPage over and over again with appropriate modifications.
Elaborating further on Ray Burns' answer: Couldn't you have your dataprocessing done in a class on a background thread and then databind the DocumentPage's properties to this class when the processing is done?
A little late to the game on this one, but I just worked out a solution to this so I thought I would share. In order to display the UI elements they have to be created on the UI thread on which they will be displayed. Since the long running task is on the UI thread, it will prevent a progress bar from updating. To get around this, I created the progress bar on a new UI thread and created the pages on the main UI thread.
Thread t = new Thread(() =>
{
ProgressDialog pd = new ProgressDialog(context);
pd.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
pd.Show();
System.Windows.Threading.Dispatcher.Run();
});
t.SetApartmentState(ApartmentState.STA);
t.IsBackground = true;
t.Start();
Action(); //we need to execute the action on the main thread so that UI elements created by the action can later be displayed in the main UI
'ProgressDialog' was my own WPF window for displaying progress information.
'context' holds the progress data for my progress dialog. It includes a cancelled property so that I can abort the action running on the main thread. It also includes a complete property so the progress dialog can close when the Action has finished.
'Action' is the method used to create all the UI elements. It monitors the context for the cancel flag and stops generating the UI elements if the flag is set. It sets the complete flag when it is done.
I don't remember the exact reason I had to set Thread 't' to an STA thread and IsBackground to true, but I am pretty sure it won't work without them.

WinForms multi-threaded databinding scenario, best practice?

I'm currently designing/reworking the databinding part of an application that makes heavy use of winforms databinding and updates coming from a background thread (once a second on > 100 records).
Let's assume the application is a stock trading application, where a background thread monitors for data changes and putting them onto the data objects. These objects are stored in a BindingList<> and implement INotifyPropertyChanged to propagate the changes via databinding to the winforms controls.
Additionally the data objects are currently marshalling the changes via WinformsSynchronizationContext.Send to the UI thread.
The user is able to enter some of the values in the UI, which means that some values can be changed from both sides. And the user values shouldn't be overritten by updates.
So there are several question coming to my mind:
Is there a general design-guildline how to do that (background updates in databinding)?
When and how to marshal on the UI thread?
What is the best way of the background thread to interact with
binding/data objects?
Which classes/Interfaces should be used? (BindingSource, ...)
...
The UI doesn't really know that there is a background thread, that updates the control, and as of my understanding in databinding scenarios the UI shouldn't know where the data is coming from... You can think of the background thread as something that pushes data to the UI, so I'm not sure if the backgroundworker is the option I'm searching for.
Sometimes you want to get some UI response during an operation in the data-/business object (e.g. setting the background during recalculations). Raising a propertychanged on a status property which is bound to the background isn't enough, as the control get's repainted after the calculation has finished? My idea would be to hook on the propertychanged event and call .update() on the control...
Any other ideas about that?
This is a hard problem since most “solutions” lead to lots of custom code and lots of calls to BeginInvoke() or System.ComponentModel.BackgroundWorker (which itself is just a thin wrapper over BeginInvoke).
In the past, I've also found that you soon wish to delay sending your INotifyPropertyChanged events until the data is stable. The code that handles one propriety-changed event often needs to read other proprieties. You also often have a control that needs to redraw itself whenever the state of one of many properties changes, and you don’t wan the control to redraw itself too often.
Firstly, each custom WinForms control should read all data it needs to paint itself in the PropertyChanged event handler, so it does not need to lock any data objects when it was a WM_PAINT (OnPaint) message. The control should not immediately repaint itself when it gets new data; instead, it should call Control.Invalidate(). Windows will combine the WM_PAINT messages into as few requests as possible and only send them when the UI thread has nothing else to do. This minimizes the number of redraws and the time the data objects are locked. (Standard controls mostly do this with data binding anyway)
The data objects need to record what has changed as the changes are made, then once a set of changes has been completed, “kick” the UI thread into calling the SendChangeEvents method that then calls the PropertyChanged event handler (on the UI thread) for all properties that have changed. While the SendChangeEvents() method is running, the data objects must be locked to stop the background thread(s) from updating them.
The UI thread can be “kicked” with a call to BeginInvoke whenever a set of update have bean read from the database. Often it is better to have the UI thread poll using a timer, as Windows only sends the WM_TIMER message when the UI message queue is empty, hence leading to the UI feeling more responsive.
Also consider not using data binding at all, and having the UI ask each data object “what has changed” each time the timer fires. Databinding always looks nice, but can quickly become part of the problem, rather then part of the solution.
As locking/unlock of the data-objects is a pain and may not allow the updates to be read from the database fast enough, you may wish to pass the UI thread a (virtual) copy of the data objects. Having the data object be persistent/immutable so that any changes to the data object return a new data object rather than changing the current data object can enable this.
Persistent objects sound very slow, but need not be, see this and that for some pointers. Also look at this and that on Stack Overflow.
Also have a look at retlang - Message-based concurrency in .NET. Its message batching may be useful.
(For WPF, I would have a View-Model that sets in the UI thread that was then updated in ‘batches’ from the multi-threaded model by the background thread. However, WPF is a lot better at combining data binding events then WinForms.)
Yes all the books show threaded structures and invokes etc. Which is perfectly correct etc, but it can be a pain to code, and often hard to organise so you can make decent tests for it
A UI only needs to be refreshed so many times a second, so performance is never an issue, and polling will work fine
I like to use a object graph that is being continuously updated by a pool of background threads. They check for actual changes in data values and when they notice an actual change they update a version counter on the root of the object graph (or on each main item whatever makes more sense) and updates the values
Then your foreground process can have a timer (same as UI thread by default) to fire once a second or so and check the version counter, and if it changes, locks it (to stop partial updates) and then refreshes the display
This simple technique totally isolates the UI thread from the background threads
There is an MSDN article specific on that topic. But be prepared to look at VB.NET. ;)
Additionally maybe you could use System.ComponentModel.BackgroundWorker, instead of a generic second thread, since it nicely formalize the kind of interaction with the spawned background thread you are describing. The example given in the MSDN library is pretty decent, so go look at it for a hint on how to use it.
Edit:
Please note: No marshalling is required if you use the ProgressChanged event to communicate back to the UI thread. The background thread calls ReportProgress whenever it has the need to communicate with the UI. Since it is possible to attach any object to that event there is no reason to do manual marshalling. The progress is communicated via another async operation - so there is no need to worry about neither how fast the UI can handle the progress events nor if the background thread gets interruped by waiting for the event to finish.
If you prove that the background thread is raising the progress changed event way too fast then you might want to look at Pull vs. Push models for UI updates an excellent article by Ayende.
I just fought a similar situation - badkground thread updating the UI via BeginInvokes. The background has a delay of 10ms on every loop, but down the road I ran into problems where the UI updates which sometimes get fired every time on that loop, can't keep up with teh freq of updates, and the app effectively stops working (not sure what happens- blew a stack?).
I wound up adding a flag in the object passed over the invoke, which was just a ready flag. I'd set this to false before calling the invoke, and then the bg thread would do no more ui updates until this flag is toggled back to true. The UI thread would do it's screen updates etc, and then set this var to true.
This allowed the bg thread to keep crunching, but allowed the ui to shut off the flow until it was ready for more.
Create a new UserControl, add your control and format it (maybe dock = fill) and add a property.
now configure the property to invoke the usercontrol and update your element, each time you change the property form any thread you want!
thats my solution:
private long value;
public long Value
{
get { return this.value; }
set
{
this.value = value;
UpdateTextBox();
}
}
private delegate void Delegate();
private void UpdateTextBox()
{
if (this.InvokeRequired)
{
this.Invoke(new Delegate(UpdateTextBox), new object[] {});
}
else
{
textBox1.Text = this.value.ToString();
}
}
on my form i bind my view
viewTx.DataBindings.Add(new Binding("Value", ptx.CounterTX, "ReturnValue"));
This is a problem that I solved in Update Controls. I bring this up not to suggest you rewrite your code, but to give you some source to look at for ideas.
The technique that I used in WPF was to use Dispatcher.BeginInvoke to notify the foreground thread of a change. You can do the same thing in Winforms with Control.BeginInvoke. Unfortunately, you have to pass a reference to a Form object into your data object.
Once you do, you can pass an Action into BeginInvoke that fires PropertyChanged. For example:
_form.BeginInvoke(new Action(() => NotifyPropertyChanged(propertyName))) );
You will need to lock the properties in your data object to make them thread-safe.
This post is old but I thought I'd give options to others. It seems once you start doing async programming and Windows Forms databinding you end up with problems updating Bindingsource datasource or updating lists bound to windows forms control. I am going to try using Jeffrey Richters AsyncEnumerator class from his powerthreading tools on wintellect.
Reason:
1. His AsyncEnumerator class automatically marshals background threads to UI threads so you can update controls as you would doing Synchronous code.
2. AsyncEnumerator simplifies Async programming. It does this automatically, so you write your code in a Synchronous fashion, but the code is still running in an asynchronous fashion.
Jeffrey Richter has a video on Channel 9 MSDN, that explains AsyncEnumerator.
Wish me luck.
-R
I am late to the party but I believe this is still a valid question.
I would advise you to avoid using data binding at all and use Observable objects instead.
The reason is, data binding looks cool and when implemented the code looks good, but data binding miserably fails when there is lot os asynchronous UI update or multi-threading as in your case.
I have personally experienced this problem with asynchronous and Databinding in prod, we even didn't detect it in testing, when users started using all different scenarios things started to break down.

Resources