英文:
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.Current
为null
。在这种情况下,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.
> - ...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论