Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF element bound to observablecollection updated on worker thread

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.

like image 919
mdutra Avatar asked Apr 01 '26 05:04

mdutra


2 Answers

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));
like image 171
kevchadders Avatar answered Apr 02 '26 22:04

kevchadders


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
}));
like image 21
VidasV Avatar answered Apr 02 '26 21:04

VidasV



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!