在非 UI 线程中创建 WPF SolidColorBrush 导致奇怪的异常。

huangapple go评论72阅读模式
英文:

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

问题

我知道在非UI线程中创建WPF UI元素(例如SolidColorBrush)是不允许的。
我无意中这样做了,但WPF没有告诉我这是不允许的,而是在MultipleCopiesCollection.get_item()方法中抛出了ArgumentOutOfRangeException

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)

[... 很多 FrameworkElement / Measure 调用堆栈]

我在DataGrid的DataGridCell的Style Setter中使用了SolidColorBrush。

我期望WPF告诉我不能在非UI线程中创建SolidColorBrush。有人知道为什么没有针对我的错误抛出适当的异常吗?

附注:这是因为Outlook/VSTO插件中的某些UI操作似乎是从Outlook消息循环调用的,导致SynchronizationContext.Currentnull。在这种情况下,await语句后面的代码可能会在非UI线程中运行。

我发现在成千上万的异常中,有一个异常是Error: Must create DependencySource on same Thread as the DependencyObject even by using Dispatcher。所以我只需要查看正确的异常就好了。

英文:

I know that it's not allowed to create WPF UI elements such as a SolidColorBrush in a non-ui-thread.
I did it by accident and instead of WPF telling me that this is not allowed, I got a ArgumentOutOfRangeException in MultipleCopiesCollection.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]

I'm using the SolidColorBrush in a Style Setter of a DataGridCell in a DataGrid.

I expect WPF to tell me that I can't create the SolidColorBrush in the Non-UI-Thread.
Does anyone know why there is no proper exception for my error?

PS: It happened to me because some UI actions in Outlook / VSTO AddIns seem to be called from the outlook message loop and lead to the fact that SynchronizationContext.Current is null. In this case code after an await statement might run in a non-ui-thread.

Found out that between the thousands of exceptions one Exception was
Error: Must create DependencySource on same Thread as the DependencyObject even by using Dispatcher.
So I just had to look at the right exception...

答案1

得分: 2

代码部分不需要翻译:

"这是一个误解,创建SolidColorBrush(或任何其他Freezable)在UI线程之外的线程是“不允许的”。

是允许的,你只需确保在在UI线程中使用该对象之前调用Freeze()

来自文档

从Freezable派生的类具有以下特性:

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

It is a misconception that creating a SolidColorBrush (or any other Freezable) in a thread other than the UI thread is "not allowed".

It is allowed, you just have to make sure to call Freeze() before you use the object in the UI thread.

From the documentation:

> A class that derives from Freezable gains the following features:
> - Special states: a read-only (frozen) state and a writable state.
> - Thread safety: a frozen Freezable object can be shared across threads.
> - ...

huangapple
  • 本文由 发表于 2023年2月24日 01:17:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/75548187.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定