WPF:如果在非 UI 线程上调用了新的 EllipseGeometry(),则异常
WPF: Exception if new EllipseGeometry() called on non UI thread
我有一个 WPF 应用程序,它从 EasyNetQ/RabbitMQ 消息队列中检索对象 'movement' 消息。正如我在记录器中看到的那样,获取消息工作正常。
private void btnSubscribeToMessageQ_Click(object sender, RoutedEventArgs e)
{
_logger.Debug("Listening for messages.");
_messageBus.Subscribe<RZMD.Messages.Movement>("test", HandleMovement);
}
处理消息发生在:
private void HandleMovement(RZMD.Messages.Movement movementMessage)
{
_logger.Debug("Movement: {0}", movementMessage);
AddCirkelToCanvasWithDispatcher(movementMessage);
_movements.Add(movementMessage);
}
UI更新如下,在canvas上画了一个圆圈:
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);
});
}
我不明白的是,为什么在 Dispatcher 之前调用 var cirkel = new EllipsGeometry()...
会抛出异常。
在调度员之前创建cirkel的中心点对象没有问题。 Ellipse 对象有何不同?
这是正确的(现代)方法吗?或者是否有更好的工具,例如 'async/await'、'TPL' 或 'Parallel Linq'
我还将动作添加到动作集合中。
我是否应该研究使用 Observable 集合和 Notify 事件来在 canvas 上绘制 cirkel?
How is the EllipseGeometry object different?
它是一个 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);
});
我有一个 WPF 应用程序,它从 EasyNetQ/RabbitMQ 消息队列中检索对象 'movement' 消息。正如我在记录器中看到的那样,获取消息工作正常。
private void btnSubscribeToMessageQ_Click(object sender, RoutedEventArgs e)
{
_logger.Debug("Listening for messages.");
_messageBus.Subscribe<RZMD.Messages.Movement>("test", HandleMovement);
}
处理消息发生在:
private void HandleMovement(RZMD.Messages.Movement movementMessage)
{
_logger.Debug("Movement: {0}", movementMessage);
AddCirkelToCanvasWithDispatcher(movementMessage);
_movements.Add(movementMessage);
}
UI更新如下,在canvas上画了一个圆圈:
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);
});
}
我不明白的是,为什么在 Dispatcher 之前调用 var cirkel = new EllipsGeometry()...
会抛出异常。
在调度员之前创建cirkel的中心点对象没有问题。 Ellipse 对象有何不同?
这是正确的(现代)方法吗?或者是否有更好的工具,例如 'async/await'、'TPL' 或 'Parallel Linq'
我还将动作添加到动作集合中。 我是否应该研究使用 Observable 集合和 Notify 事件来在 canvas 上绘制 cirkel?
How is the EllipseGeometry object different?
它是一个 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);
});