为什么这个WPF TreeViewItem风格导致交叉线程问题?
我有以下样式应用于treeviewitem容器。 基本上,用于覆盖选择颜色:
<Style x:Key="element-designer-node-host" TargetType="{x:Type TreeViewItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"
Color="{DynamicResource nav-tvi-sel-bg1}" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="{DynamicResource nav-tvi-sel-bg1}" />
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
Color="{DynamicResource nav-tvi-sel-bg2}" />
</Style.Resources>
<Setter Property="IsExpanded" Value="{Binding Expanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding Selected, Mode=TwoWay}" />
</Style>
应用于树视图:
<TreeView
ItemContainerStyle="{StaticResource element-designer-node-host}"
ItemsSource="{Binding Nodes}">
现在,我在一个新线程中启动一个带有这个树视图的窗口,并且一切正常。
在那个窗口关闭之后,我在一个全新的线程中开始全新的窗口,当我尝试点击某个节点时,出现异常:
调用线程不能访问这个对象,因为不同的线程拥有它。
在System.Windows.Threading.Dispatcher.VerifyAccess()在System.Windows.Freezable.System.Windows.ISealable.get_IsSealed()在System.Windows.StyleHelper.SealIfSealable(对象的值)在System.Windows.StyleHelper.GetChildValueHelper(UncommonField 1 dataField, ItemStructList
System.Windows.StyleHelper.GetChildValue(UncommonField 1 dataField, DependencyObject container, Int32 childIndex, FrameworkObject child, DependencyProperty dp, FrugalStructList
1 dataField, ItemStructList
1&valueLookupList,DependencyProperty dp,DependencyObject container,FrameworkObject child,Int32 childIndex,Boolean styleLookup,EffectiveValueEntry&entry,ValueLookupType&sourceType,FrameworkElementFactory templateRoot)在System.Windows.StyleHelper.GetValueFromTemplatedParent(DependencyObject容器,Int32 childIndex,FrameworkObject子级,DependencyProperty dp,FrugalStructList 1& childRecordFromChildIndex, FrameworkElementFactory templateRoot, EffectiveValueEntry& entry)
)中的
at System.Windows.FrameworkElement.GetValueFromTemplatedParent(DependencyProperty dp, EffectiveValueEntry& entry) at System.Windows.FrameworkElement.GetRawValue(DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry& entry) at System.Windows.FrameworkElement.EvaluateBaseValueCore(DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry& newEntry) at System.Windows.DependencyObject.EvaluateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry newEntry, OperationType operationType) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue) at System.Windows.StyleHelper.InvalidateDependents(Style ownerStyle, FrameworkTemplate frameworkTemplate, DependencyObject container, DependencyProperty dp, FrugalStructList1 dataField, DependencyObject container, Int32 childIndex, FrameworkObject child, DependencyProperty dp, FrugalStructList
1&childRecordFromChildIndex,EffectiveValueEntry&entry,ValueLookupType&sourceType,FrameworkElementFactory templateRoot) 1& childRecordFromChildIndex, FrameworkElementFactory templateRoot, EffectiveValueEntry& entry)
在System.Windows.StyleHelper.OnTriggerSourcePropertyInvalidated(Style ownerStyle,FrameworkTemplate frameworkTemplate,DependencyObject容器,DependencyProperty dp,DependencyPropertyChangedEventArgs changedArgs)中
at System.Windows.FrameworkElement.GetValueFromTemplatedParent(DependencyProperty dp, EffectiveValueEntry& entry) at System.Windows.FrameworkElement.GetRawValue(DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry& entry) at System.Windows.FrameworkElement.EvaluateBaseValueCore(DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry& newEntry) at System.Windows.DependencyObject.EvaluateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry newEntry, OperationType operationType) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue) at System.Windows.StyleHelper.InvalidateDependents(Style ownerStyle, FrameworkTemplate frameworkTemplate, DependencyObject container, DependencyProperty dp, FrugalStructList1& childRecordFromChildIndex, FrameworkElementFactory templateRoot, EffectiveValueEntry& entry)
1&dependents,Boolean invalidateOnlyContainer) ,布尔invalidateOnlyContainer,在System.Windows.DependencyObject.UpdateEffectiveValue FrugalStructList`1&在System.Windows.FrameworkElement.OnPropertyChanged triggerSourceRecordFromChildIndex,FrugalMap&propertyTriggersWithActions,的Int32 sourceChildIndex)(DependencyPropertyChangedEventArgs e)上System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs参数)(entryIndex entryIndex ,DependencyProperty dp,PropertyMetadata元数据,EffectiveValueEntry oldEntry,EffectiveValueEntry&newEntry,布尔coerceWithDeferredReference, System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp,Object value,PropertyMetadata metadata,Boolean coerceWithDeferredReference,Boolean coerceWithCurrentValue,OperationType operationType,Boolean isInternal)在System.Windows.DependencyObject.SetValue(DependencyProperty dp,Object value) )System.Windows.Controls.TreeView.ChangeSelection(Object data,TreeViewItem container,Boolean selected)在System.Windows.Controls.TreeViewItem.Select(布尔选中)在System.Windows.Controls.TreeViewItem.OnGotFocus(RoutedEventArgs e)
at System.Windows.FrameworkElement.GetValueFromTemplatedParent(DependencyProperty dp, EffectiveValueEntry& entry) at System.Windows.FrameworkElement.GetRawValue(DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry& entry) at System.Windows.FrameworkElement.EvaluateBaseValueCore(DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry& newEntry) at System.Windows.DependencyObject.EvaluateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry newEntry, OperationType operationType) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue) at System.Windows.StyleHelper.InvalidateDependents(Style ownerStyle, FrameworkTemplate frameworkTemplate, DependencyObject container, DependencyProperty dp, FrugalStructList
在System.Windows.UIElement.IsFocused_Changed(的DependencyObject d,DependencyPropertyChangedEventArgs e)上System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)上System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)上System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs ARGS )在System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex,DependencyProperty dp,PropertyMetadata元数据,EffectiveValueEntry oldEntry,EffectiveValueEntry&newEntry,布尔coerceWithDeferredReference,布尔coerceWithCurrentValue,OperationType操作类型)在System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp,对象值,PropertyMetadata在System.Wi上System.Windows.DependencyObject.SetValue(DependencyPropertyKey键,对象值)的布尔coerceWithDeferredReference,布尔coerceWithCurrentValue,OperationType操作类型,布尔isInternal) ndows.Input.FocusManager.OnFocusedElementChanged(DependencyObject的d,DependencyPropertyChangedEventArgs e)上System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)上System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)上System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs参数) System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex,DependencyProperty dp,PropertyMetadata metadata,EffectiveValueEntry oldEntry,EffectiveValueEntry&newEntry,Boolean coerceWithDeferredReference,Boolean coerceWithCurrentValue,OperationType operationType) ,布尔coerceWithDeferredReference,布尔coerceWithCurrentValue,OperationType操作类型,布尔isInternal)在System.Windows.Input.FocusManager.SetFocusedElement(DependencyObject元素,IInputElement 值System.Windows.Input.KeyboardNavigation.UpdateFocusedElement(DependencyObject focusTarget)System.Windows.FrameworkElement.OnGotKeyboardFocus(Object sender,KeyboardFocusChangedEventArgs e)at System.Windows.Input.KeyboardFocusChangedEventArgs.InvokeEventHandler(Delegate genericHandler,Object genericTarget)at System在System.Windows .Windows.RoutedEventArgs.InvokeHandler(委托处理程序,对象目标)在System.Windows.RoutedEventHandlerInfo.InvokeHandler(对象目标,RoutedEventArgs routedEventArgs)在System.Windows.EventRoute.InvokeHandlersImpl(对象源,RoutedEventArgs指定参数时,布尔再加注) .UIElement.RaiseEventImpl(DependencyObject的发件人,RoutedEventArgs参数)在System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs参数)在System.Windows.UIElement.RaiseEvent(RoutedEventArgs指定参数时,布尔信任)在System.Windows.Input.InputManager.ProcessStagingArea()在System.Windows.Input的System.Windows.Input.InputManager.ProcessInput(InputEventArgs输入) 在System.Windows.In.Input.KeyboardDevice.TryChangeFocus(DependencyObject newFocus,IKeyboardInputProvider keyboardInputProvider,布尔askOld,布尔askNew,布尔forceToNullIfFailed)System.Windows.Input.KeyboardDevice.Focus(DependencyObject焦点)上的.KeyboardDevice.ChangeFocus(DependencyObject焦点,Int32时间戳) ,布尔askOld,布尔askNew,布尔forceToNullIfFailed)在System.Windows.Input.KeyboardDevice.Focus(IInputElement元件)在System.Windows.UIElement.Focus()在System.Windows.Controls.TreeViewItem.OnMouseLeftButtonDown(MouseButtonEventArgs E)在系统.Windows.UIElement.OnMouseLeftButtonDownThunk(对象发件人,MouseButtonEventArgs e)上System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler在System.Windows(代表genericHandler,对象genericTarget)在System.Windows.RoutedEventArgs.InvokeHandler(委托处理程序,对象目标)。在System.Windows.EventRoute.Invok RoutedEventHandlerInfo.InvokeHandler(对象目标,RoutedEventArgs routedEventArgs) eHandlersImpl在System.Windows.UIElement.OnMouseDownThunk在System.Windows.UIElement.ReRaiseEventAs(对象源,RoutedEventArgs指定参数时,布尔再加注)(DependencyObject的发件人,RoutedEventArgs指定参数时,RoutedEvent newEvent)(对象发件人,MouseButtonEventArgs E)...
为什么会发生这种情况,解决方案是什么?
请注意,当我从样式资源中删除这三个笔刷覆盖时,问题不会发生。
看起来样式的实际引用保留在element-designer-node-host
的内存中。 这使得引用的所有者成为已被销毁的线程。 来自MSDN的更多信息。
这可能与第一次使用这些资源的新线程有关,但是没有看到更多的代码,这更像是一种猜测。
解决方法是在UI线程上创建新Window
,或者使用x:Shared="false"
创建新Window
,然后使用新创建的每个用法的引用,而不是使用共享引用。 请记住,这会增加应用程序的内存占用量,并且如果目标计算机的可用内存量有限,则可能会导致内存不足异常。
来自MSDN的更多信息 - OutOfMemoryException。
上一篇: Why this WPF TreeViewItem style is causing cross thread issues?
下一篇: WPF Window The given Key was not present in the Dictionary