首页 文章

为什么这个WPF TreeViewItem样式导致交叉线程问题?

提问于
浏览
2

我有以下样式应用于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(UncommonField1 System.Windows.StyleHelper.GetChildValue中的dataField,ItemStructList1&valueLookupList,DependencyProperty dp,DependencyObject容器,FrameworkObject子,Int32 childIndex,Boolean styleLookup,EffectiveValueEntry&entry,ValueLookupType&sourceType,FrameworkElementFactory templateRoot)(UncommonField1 dataField,DependencyObject容器,Int32 childIndex,FrameworkObject子, System.Windows.StyleHelper.GetValueFromTemplatedParent的DependencyProperty dp,FrugalStructList1&childRecordFromChildIndex,EffectiveValueEntry&entry,ValueLookupType&sourceType,FrameworkElementFactory templateRoot)(DependencyObject容器,Int32 childIndex,FrameworkObject子,DependencyProperty dp,FrugalStructList1&childRecordFromChildIndex,Fr System.Windows.FrameworkElement.EvaluateBaseValueCore(DependencyProperty dp)上System.Windows.FrameworkElement.GetRawValue(DependencyProperty dp,PropertyMetadata metadata,EffectiveValueEntry&entry)的System.Windows.FrameworkElement.GetValueFromTemplatedParent(DependencyProperty dp,EffectiveValueEntry&entry)中的ameworkElementFactory templateRoot,EffectiveValueEntry&entry) System.Windows.DependencyObject.UpdateEffectiveValue上的System.Windows.DependencyObject.EvaluateEffectiveValue(EntryIndex entryIndex,DependencyProperty dp,PropertyMetadata metadata,EffectiveValueEntry oldEntry,EffectiveValueEntry newEntry,OperationType operationType)中的,PropertyMetadata元数据,EffectiveValueEntry和newEntry(EntryIndex entryIndex,DependencyProperty dp,PropertyMetadata)的元数据,EffectiveValueEntry oldEntry,EffectiveValueEntry&newEntry,布尔coerceWithDeferredReference,布尔coerceWithCurrentValue,operationType operationType)在System.Windows.DependencyObject.InvalidateProper TY(的DependencyProperty DP,布尔preserveCurrentValue)在System.Windows.StyleHelper.InvalidateDependents(风格ownerStyle,FrameworkTemplate frameworkTemplate,DependencyObject的容器,的DependencyProperty DP,FrugalStructList1&家属,布尔invalidateOnlyContainer)在System.Windows.StyleHelper.OnTriggerSourcePropertyInvalidated(风格ownerStyle,FrameworkTemplate frameworkTemplate, DependencyObject的容器,的DependencyProperty DP,DependencyPropertyChangedEventArgs changedArgs,布尔invalidateOnlyContainer,FrugalStructList`1&triggerSourceRecordFromChildIndex,在System.Windows.FrameworkElement.OnPropertyChanged在系统在System.Windows.DependencyObject.NotifyPropertyChange FrugalMap&propertyTriggersWithActions,的Int32 sourceChildIndex)(DependencyPropertyChangedEventArgs E)(DependencyPropertyChangedEventArgs参数) . Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex,DependencyProperty dp,PropertyMetadata metadata,EffectiveValueEntry oldEntry,Effec System.Windows.DependencyObject.SetValue上的System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp,Object value,PropertyMetadata metadata,Boolean coerceWithDeferredReference,Boolean coerceWithCurrentValue,OperationType operationType,Boolean isInternal)中的tiveValueEntry&newEntry,Boolean coerceWithDeferredReference,Boolean coerceWithCurrentValue,OperationType operationType) (的DependencyProperty DP,对象的值)在System.Windows.Controls.TreeView.ChangeSelection(对象数据,树型视图容器,布尔选择的)在System.Windows.Controls.TreeViewItem.Select(布尔选择的)在System.Windows.Controls.TreeViewItem . OnGotFocus(RoutedEventArgs e)上System.Windows.UIElement.IsFocused_Changed(的DependencyObject d,DependencyPropertyChangedEventArgs e)上System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)上在System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs参数)在System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex,的DependencyProperty DP,PropertyMetadata元数据,EffectiveValueEntry oldEntry,EffectiveValueEntry&newEntry,布尔coerceWithDeferredReference System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)中, System.Windows.DependencyObject.SetValue(DependencyPropertyKey key,Object value)中的System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp,Object value,PropertyMetadata metadata,Boolean coerceWithDeferredReference,Boolean coerceWithCurrentValue,OperationType operationType,Boolean isInternal)中的布尔coerceWithCurrentValue,OperationType operationType) )在System.Windows.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.UpdateEffectiveValue(EntryIndex entryIndex,的DependencyProperty DP,PropertyMetadata元数据,EffectiveValueEntry oldEntry,EffectiveValueEntry&newEntry,布尔coerceWithDeferredReference ,System.Windows.Input.FocusManager.SetFocusedElement(DependencyObject元素)中的System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp,Object value,PropertyMetadata metadata,Boolean coerceWithDeferredReference,Boolean coerceWithCurrentValue,OperationType operationType,Boolean isInternal)中的布尔coerceWithCurrentValue,OperationType operationType) ,IInputElement值)System.Windows.Input.KeyboardNavigation.UpdateFocusedElement(DependencyObject的focusTarget)在System.Windows.FrameworkElement.OnGotKeyboardFocus(对象发件人,KeyboardFocusChangedEventAr gs e)在System.Windows.RindtedEventArgs.InvokeHandler(委托处理程序,对象目标)的System.Windows.Input.KeyboardFocusChangedEventArgs.InvokeEventHandler(Delegate genericHandler,Object genericTarget)处于System.Windows.RoutedEventHandlerInfo.InvokeHandler(对象目标,RoutedEventArgs routedEventArgs)在System.Windows.EventRoute.InvokeHandlersImpl在System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs参数)在System.Windows在System.Windows.UIElement.RaiseEventImpl(对象源,RoutedEventArgs指定参数时,布尔再加注)(DependencyObject的发件人,RoutedEventArgs参数) . UIElement.RaiseEvent(RoutedEventArgs指定参数时,布尔信任)在System.Windows.Input.InputManager.ProcessStagingArea()在System.Windows.Input.InputManager.ProcessInput(InputEventArgs输入)在System.Windows.Input.KeyboardDevice.ChangeFocus(DependencyObject的焦点, System.Windows.Input.KeyboardDevice.TryChangeFocus中的Int32时间戳(DependencyObject newFocus,IKeyboardInputProvider keyboardInputProvider,Bo齐墩果askOld,布尔askNew,布尔forceToNullIfFailed)在System.Windows.Input.KeyboardDevice.Focus(DependencyObject的焦点,布尔askOld,布尔askNew,布尔forceToNullIfFailed)在System.Windows.Input.KeyboardDevice.Focus(IInputElement元件)在System.Windows .UIElement.Focus()在System.Windows.Uindlement.OnMouseLeftButtonDownThunk(Object sender,MouseButtonEventArgs e)的System.Windows.Controls.TreeViewItem.OnMouseLeftButtonDown(MouseButtonEventArgs e)处于System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler,Object) System.Windows.RindtedEventHandlerInfo.InvokeHandler(Object target,RoutedEventArgs routedEventArgs)中的System.Windows.RoutedEventArgs.InvokeHandler(委托处理程序,Object目标)处于System.Windows.EventRoute.InvokeHandlersImpl(Object source,RoutedEventArgs args,Boolean reRaised)的genericTarget) System.Windows上的System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender,RoutedEventArgs args,RoutedEvent newEvent) .UIElement.OnMouseDownThunk(Object sender,MouseButtonEventArgs e)...

为什么会发生这种情况,解决方案是什么?

Note that when I remove those three brush overrides from style resources, the problem does not occur.

1 回答

  • 2

    似乎样式的实际引用保留在 element-designer-node-host 的内存中 . 这使得引用的所有者成为已被销毁的线程 . More info from MSDN .
    这可能与第一次使用这些资源的新线程有关,但是没有看到更多的代码,这更像是一种猜测 .
    解决方案是要么在UI线程上创建新的 Window ,要么使用 x:Shared="false" 然后依次使用新创建的引用而不是使用共享引用 . 请记住,这会增加应用程序的内存占用,如果目标计算机的可用内存有限,则可能导致内存不足 .
    更多信息来自MSDN - OutOfMemoryException .

相关问题