WPF:如果在非UI线程上调用新的EllipseGeometry(),则出现异常

WPF:如果在非UI线程上调用新的EllipseGeometry(),则出现异常,wpf,multithreading,canvas,dispatcher,pathgeometry,Wpf,Multithreading,Canvas,Dispatcher,Pathgeometry,我有一个WPF应用程序,它从EasyNetQ/RabbitMQ消息队列检索对象“移动”消息。从我的记录器中可以看到,获取消息工作正常 private void btnSubscribeToMessageQ_Click(object sender, RoutedEventArgs e) { _logger.Debug("Listening for messages."); _messageBus.Subscribe<RZMD.Messages.Movement>("test",

我有一个WPF应用程序,它从EasyNetQ/RabbitMQ消息队列检索对象“移动”消息。从我的记录器中可以看到,获取消息工作正常

private void btnSubscribeToMessageQ_Click(object sender, RoutedEventArgs e)
{
  _logger.Debug("Listening for messages.");
  _messageBus.Subscribe<RZMD.Messages.Movement>("test", HandleMovement);
}
通过在画布上绘制圆环,UI更新如下:

private void AddCirkelToCanvasWithDispatcher(RZMD.Messages.Movement movementMessage)
{
  var center = new Point(movementMessage.X, movementMessage.Y);
  //var cirkel = new EllipseGeometry() { Center = center, RadiusX = 5, RadiusY = 5 }; << 
  // above line causes exception re threads
  // System.InvalidOperationException: 'The calling thread cannot access 
  // this object because a different thread owns it.'

  Application.Current.Dispatcher.Invoke( ()=>
  {
    //if I put new EllipseGeometry() here all is fine
    var cirkel = new EllipseGeometry() { Center = center, RadiusX = 5, RadiusY = 5 };
    var path = new Path() { Stroke = Brushes.Black, Data = cirkel };
    cnvFloor.Children.Add(path);
  });
}
private void addCirketocanvaswithDispatcher(RZMD.Messages.Movement movementMessage)
{
变量中心=新点(movementMessage.X,movementMessage.Y);
//var cirkel=新的椭圆几何法(){Center=Center,RadiusX=5,RadiusY=5};
{
//如果我把新的椭圆仪放在这里,一切都很好
var cirkel=新的椭圆几何法(){Center=Center,RadiusX=5,RadiusY=5};
var path=newpath(){Stroke=brusks.Black,Data=cirkel};
cnvFloor.Children.Add(路径);
});
}
我不明白的是,为什么调用
var cirkel=new ellipsgometry()…
会在调度程序之前抛出异常。 在dispatcher之前创建cirkel的中心点对象没有问题。椭圆对象有何不同

这是正确的(现代)方法吗?或者是否有更好的工具,如“异步/等待”、“TPL”或“并行Linq”

此外,我还将动作添加到动作集合中。 我是否应该使用可观察的集合进行调查,并通知事件在画布上绘制cirkel

椭圆测量对象有何不同

它是一个
System.Windows.Threading.DispatcherObject
,因此具有线程关联性,即除非它被冻结,否则只能在创建它的线程中访问它

您可以将其冻结以使其跨线程访问,而不是在Dispatcher操作中创建EllipseGeometry:

var cirkel = new EllipseGeometry() { Center = center, RadiusX = 5, RadiusY = 5 };
cirkel.Freeze();

Application.Current.Dispatcher.Invoke(() =>
{
    var path = new Path() { Stroke = Brushes.Black, Data = cirkel };
    cnvFloor.Children.Add(path);
});
椭圆测量对象有何不同

它是一个
System.Windows.Threading.DispatcherObject
,因此具有线程关联性,即除非它被冻结,否则只能在创建它的线程中访问它

您可以将其冻结以使其跨线程访问,而不是在Dispatcher操作中创建EllipseGeometry:

var cirkel = new EllipseGeometry() { Center = center, RadiusX = 5, RadiusY = 5 };
cirkel.Freeze();

Application.Current.Dispatcher.Invoke(() =>
{
    var path = new Path() { Stroke = Brushes.Black, Data = cirkel };
    cnvFloor.Children.Add(path);
});

啊。。。我在某个地方读到过关于这种冷冻的东西,但没有意识到它对线程的影响。我要试一试。如果您序列化了
System.Windows.Threading.DispatcherObject
并随后对其进行反序列化,
对象
不再冻结,那么也要感谢您。我昨天在这件事上绊倒了…啊。。。我在某个地方读到过关于这种冷冻的东西,但没有意识到它对线程的影响。我要试一试。如果您序列化了
System.Windows.Threading.DispatcherObject
并随后对其进行反序列化,
对象
不再冻结,那么也要感谢您。我昨天在这件事上绊倒了。。。