我有一个在wpf中生成GUI元素的线程。画布用于绘制对象(矩形等等......)
这个 wpf线程调用另一个线程,我们将其命名为计算线程。该线程计算要在画布中显示的元素的大小和位置等。
我想让这两个部分(GUI和计算)在不同的线程中运行。 “计算线程”基于库而不引用wpf功能。
现在我想显示wpf线程显示的计算线程的中间数据。 我这样做:
calc-thread触发由wpf-thread实现的事件(DataReady):
void MyRegStringObject_DataReady()
{
if (DebugMode)
MyDrawingBoard.DrawRegElements();
}
现在的问题是,抛出一个错误:“调用线程无法访问此对象,因为另一个线程拥有它”
在stackoverflow中有一些回答的问题引用了这个错误,但在我的情况下,它们都没有帮助。
DrawRegElements()函数想要清除画布对象(以及其他内容):
curCanvas.Children.Clear();
在代码中的这个位置抛出错误。 看来,来自calc-thread的事件触发的函数MyRegStringObject_DataReady也由calc-thread承担。但是在类中定义了wpf-thread基于。
我该如何解决这个问题?有谁有想法吗? 顺便说说: calc方法以这种方式调用:
CalcElements = Task.Factory.StartNew<bool>(MyRegStringObject.CalcRegElements);
线程完成后我定义了:
CalcElements.ContinueWith((FinishCalcRegElements) =>
{
MyDrawingBoard.DrawRegElements();
}, CancellationToken.None, TaskContinuationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext());
没问题。 Everythins运行完美。 ContinueWith中定义的函数似乎是由wpf-thread所有。
答案 0 :(得分:2)
错误消息很简单,您正在尝试从现在拥有的线程访问UI元素。将此工作委托给与主UI线程关联的WPF Dispatcher,它将所有消息从工作线程发布到UI线程:
Application.Current.Dispatcher.BeginInvoke((ThreadStart)delegate
{
MyDrawingBoard.DrawRegElements();
});
为了确保您使用与主UI线程关联的正确Dispatcher,您可以将其作为参数传递给工作线程代码,因此只需从主UI线程传递Dispatcher.Current
,否则调用{{工作线程中的1}}将初始化与调用工作线程关联的新实例。或者只使用引用主UI线程的Dispatcher的Dispatcher.CurrentDispatcher
。
PS:
但是在类中定义了wpf-thread基于
这是错误的假设,类本身与任何线程无关。 Concrtete类实例是。因此,您可以在UI或工作线程中创建UI /非UI相关类。
线程Application.Current.Dispatcher
事件被触发的重要一点是什么?