UPDATE
I have solved this problem. I found I wasn't properly synchronising access to the line and chart objects. Instead of locking them for the duration of the handler, I locked them only for the moment they were used. I think something inside the Dynamic Data Display library was using deferred execution and trying to access one of the objects when I wasn't expecting it.
TL;DR: Properly synchronise locks.
I'm currently working on a GUI using WPF to visualise an algorithm in some class library. All of the controls I'm using within the GUI are either standard WPF or from the Microsoft Dynamic Data Display library.
I'm getting the very common "The calling thread cannot access this object because a different thread owns it" error. I have done a fair amount of searching around but cannot find a solution to this myself.
Right now, I'm a little confused as to how to add lines to the chart if the thread doesn't own it. I've tried using the dispatcher as many other answers on this site have suggested, but it hasn't solved this.
The summary window is intended to be a child window of the main window, which opens before the simulation runs and display data in real time.
The simulator publishes a number of events which are all handled asynchronously (internally, it uses BeginInvoke and EndInvoke). Could this cause a problem in this scenario?
The summary view model registers a number of visualisations, which in turn create their own controls and add them to a canvas provided by the summary window.
A very brief outline of the code is below
public class MainWindowModel
{
//...
public async void RunSimulation()
{
WindowService.OpenWindowFor<SimulationSummaryViewModel>(SimSummaryVM);
await Simulator.Run();
}
}
public class SimulatorSummaryViewModel
{
//...
public SimulatorSummaryViewModel()
{
Visualisations.Add(new RealTimeChart());
}
//...
}
public class RealTimeChart : IVisualisation
{
// ...
private ChartPlotter _Chart; //From Dynamic Data Display library
//Handles adding information to the current line
private void OnSimulatorStepHandler(Args a)
{
/* The exception occurs in here, when adding a data point,
whilst another handler is adding a line to the chart.
I have tried adding a lock to the chart and line objects, but it had no effect
*/
}
//Handles adding the current line to the chart
private void OnSimulatorRepetitionComplete(Args a)
{
//lineToAdd is an EnumerableDataSource<DataPoint>.
//DataPoint is a simple class with two primitive properties.
_Chart.Dispatcher.Invoke(new Action(()=>
{
_Chart.AddLineGraph(lineToAdd);
}));
}
}
public class SummaryWindow : Window
{
// ...
public SummaryWindow()
{
// ...
foreach(IVisualisation Vis in ViewModel.Visualisations)
{
Vis.Draw(this.VisCanvas);
}
}
}