在非 UI-Thread 中创建 WPF SolidColorBrush 导致奇怪的异常 [已关闭]

Create WPF SolidColorBrush in Non-UI-Thread leads to strange exception [closed]

提问人:Lumo 提问时间:2/24/2023 最后编辑:Lumo 更新时间:2/24/2023 访问量:69

问:


编辑问题以包括所需的行为、特定问题或错误以及重现问题所需的最短代码。这将有助于其他人回答这个问题。

9个月前关闭。

我知道不允许在非 ui 线程中创建 WPF UI 元素,例如 SolidColorBrush。 我是偶然这样做的,而不是 WPF 告诉我这是不允许的,我得到了一个:ArgumentOutOfRangeExceptionMultipleCopiesCollection.get_item()

System.Windows.Controls.MultipleCopiesCollection.get_Item(Int32 index) System.Windows.Data.ListCollectionView.InternalItemAt(Int32 index) System.Windows.Data.ListCollectionView.GetItemAt(Int32 index) System.Windows.Controls.ItemCollection.GetItemAt(Int32 index) System.Windows.Controls.DataGridCellsPanel.VirtualizeChildren(List1 blockList, IItemContainerGenerator generator)
System.Windows.Controls.DataGridCellsPanel.GenerateAndMeasureChildrenForRealizedColumns(Size constraint)
System.Windows.Controls.DataGridCellsPanel.MeasureOverride(Size constraint)
System.Windows.FrameworkElement.MeasureCore(Size availableSize)
System.Windows.UIElement.Measure(Size availableSize)
MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
System.Windows.Controls.ItemsPresenter.MeasureOverride(Size constraint)
System.Windows.FrameworkElement.MeasureCore(Size availableSize)

[... a lot more FrameworkElement / Measure call stack]

我在 DataGrid 中 DataGridCell 的样式设置器中使用 SolidColorBrush。

我希望 WPF 告诉我,我无法在非 UI-Thread 中创建 SolidColorBrush。 有谁知道为什么我的错误没有适当的例外?

PS:它发生在我身上,因为Outlook / VSTO加载项中的某些UI操作似乎是从Outlook消息循环中调用的,并导致了以下事实。在这种情况下,语句后面的代码可能会在非 ui-thread 中运行。SynchronizationContext.Currentnullawait

发现在数千个异常中,有一个异常是 。 所以我只需要看看正确的例外......Error: Must create DependencySource on same Thread as the DependencyObject even by using Dispatcher

WPF 多线程异常 DataGrid 样式

评论

0赞 BionicCode 2/24/2023
SolidColorBrush 是一个 DispatcherObject。DispatcherObject 可以在任何地方实例化,就像任何其他类型的类型一样。创建后,它将与当前线程的 Dispatcher 相关联。若要从任何其他线程访问 DispatcherObject,需要使用关联的 Dispatcher 进行访问,以避免跨线程异常。如果对象是冻结的 Freezable,则会解除 Dispatcher 关联(并且实例与依赖项属性系统解除关联),并且可以使用任何 Dispatcher 引用该实例。
0赞 BionicCode 2/24/2023
换言之,创建对象不是问题,而是哪个 Dispatcher 执行引用代码。您的错误可能发生在任何非法引用之前。如果不查看代码,就无法判断确切原因。
0赞 BionicCode 2/24/2023
更新后的错误消息是关于使用 DispatcherObject (SolidColorBrush) 的,而不是关于创建它的。这应该很清楚。创建对象时永远不会引发跨线程异常(与您的期望相反:“我希望 WPF 告诉我,我无法在非 UI 线程中创建 SolidColorBrush”)。交叉线程始终与消费(引用)有关。

答:

2赞 Clemens 2/24/2023 #1

在UI线程以外的线程中创建(或任何其他)是“不允许”的,这是一种误解。SolidColorBrushFreezable

这是允许的,您只需要确保在使用 UI 线程中的对象之前调用即可。Freeze()

文档中:

派生自 Freezable 的类获得以下功能:

  • 特殊状态:只读(冻结)状态和可写状态。
  • 线程安全:冻结的 Freezable 对象可以在线程之间共享。
  • ...

评论

0赞 Lumo 2/24/2023
好点,谢谢你有这个。虽然这不是我要求的;)