Proper way to handle real-time data??

Oct 10, 2012 at 7:32 PM

I've been playing around with OxyPlot and found it to almost be a certainty that I recieve a "Collection was modified; enumeration operation may not execute." exception if I try to pan / zoom while adding points to the graph in real time.

What is the proper way to refresh the plot while running?

What is the proper way to add points as to not cause this exception?

Best Regards,

Eric

Oct 10, 2012 at 10:07 PM

Hi Eric, OxyPlot is not locking the model while refreshing. I would like to keep the library simple and think thread synchronization should be handled in the client code (I guess the alternative is to add synchronization objects to every list in the plotmodel?). Please comment everyone that knows more about this than me :-) You could also create a minimal example that we can include in the library, and we will help to make it thread-safe!

Oct 17, 2012 at 3:47 PM
Edited Oct 17, 2012 at 4:10 PM
So far, the safest way I have found of asynchronously updating a chart series is to add the points to the series from the point generating thread, using the UI dispatcher. Here is a view model which demonstrates this:
namespace MyPlot
{
	public class MyPlotViewModel : INotifyPropertyChanged
	{
		public MyPlotViewModel()
		{
			DataPlot = new PlotModel();

			DataPlot.Series.Add(new LineSeries()
			{
				Title = "Sin(x)",
				Points = new List<IDataPoint>()
			});

			m_userInterfaceDispatcher = Dispatcher.CurrentDispatcher;
			var thread = new Thread(new ThreadStart(AddPoints));
			thread.Start();

		}

		public void AddPoints()
		{
			var x = 0.0;
			var addPoints = true;
			while (addPoints)
			{
				try
				{

					m_userInterfaceDispatcher.Invoke(() =>
					{
						(DataPlot.Series[0] as LineSeries).Points.Add(new DataPoint(x, Math.Sin(x)));
						if (PropertyChanged != null)
						{
							DataPlot.InvalidatePlot(true);
						}

					});
				}
				catch (TaskCanceledException e)
				{
					addPoints = false;
				}
				x = x + 2 * Math.PI / 100;
				Thread.Sleep(10);
			}
		}

		public PlotModel DataPlot
		{
			get; set;
		}

		public event PropertyChangedEventHandler PropertyChanged;

		private Dispatcher m_userInterfaceDispatcher;
	}
}
Oct 17, 2012 at 10:25 PM

Thanks for the example Dave!

Also see the new example using TPL (Examples/Wpf/WpfExamples/Examples/TaskDemo).
I tried to update the plot in a task running with the SynchronizationContext of the UI thread.

Mar 9, 2013 at 3:27 PM
Edited Mar 9, 2013 at 3:27 PM
Thanks Dave for the example. I tried to implement it but it shows me the below error. Any idea please. Appreciate your help.

Error 3 Cannot convert lambda expression to type 'System.Delegate' because it is not a delegate type