我一直在处理多线程问题。在过去的几天里,我一直在努力确保我的所有电话都是线程安全的。我刚刚碰到了一个问题。这是场景:
我正在尝试使用Infragistics XamDataChart控件绘制波形,该控件以500点/秒/波形传递。在启动应用程序时,我创建了具有名为WaveData的ObservableCollection属性的对象,这些属性直接绑定到itemscontrol中的xaml。当数据进入时,它存储在队列中,生成的工作线程用于使数据出列并在适当的位置更新集合。
Spawn工作线程:
QueueProcessThread = Task.Factory.StartNew(() => UpdateWaveFormCollections(WaveForms), tokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
用于更新循环中运行的集合的代码(为简洁起见省略了一些代码行):
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++;
}
正如您所看到的,我实际上并没有在集合中添加/删除项目,而只是在特定位置更新项目。这是因为我希望它看起来像医院的病人监护仪。
我遇到的问题是我意识到我正在非UI线程上更新此集合,并且该集合直接绑定到Infragistics LineSeries ... ,这是有效的。但是,当我在非UI线程上更新该集合时,另一个使用Infragistics StepLineSeries的图会引发异常。 我怎么可能在非UI线程上更新绑定集合?我对此感到担心,因为1)偶尔我会收到一个错误,即在非UI上无法更新集合线程和2)当我通过调度程序将波形更新切换到UI线程时,性能非常差,GUI无法使用。我需要理解为什么这样有效,所以我知道如何继续。由于我的线程管理不善,我不想部署可能随时失败的应用程序。我正在寻找可能的原因/如何在非UI线程上更新绑定的ObservableCollection。任何帮助/建议将不胜感激。
答案 0 :(得分:3)
也许您需要考虑使用Dispatcher(除非省略了部分代码)。
当您执行需要在UI线程上执行代码的操作时,可以使用Dispatcher方法。
也许您可以在后台工作线程中检索该数据,当您更新集合时,将更改传播回UI线程
e.g。
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
new Action(() => methodHere = 50));
答案 1 :(得分:1)
尝试使用调度程序调用以确保将通过UI线程访问该集合,从而不允许在非UI线程上触发任何其他事件。
Application.Current.Dispatcher.BeginInvoke(new Action(()=>
{
// code here to access collection
}));
答案 2 :(得分:0)
我正在寻找的答案是你可以更新数据绑定对象的属性,WPF将负责为你调度,但是,你不能从非UI线程更新集合(添加/删除/清除)。在我的波形中,我没有添加点,而是在特定索引处更新项目的值。但是,在另一种情况下,我总是添加和删除点。