【发布时间】:2021-10-11 22:38:24
【问题描述】:
我有一个 WPF 应用程序,在 UI 线程上有一个长时间运行的任务,我想为其显示一个进度条 (*)。由于 UI 很忙,遵循this 解决方案,我选择在单独的 UI/STA-Thread 上打开带有进度条的窗口。
一切正常 - 我第一次创建窗口。问题显然是窗口使用Style="{StaticResource CustomWindowStyle}" 并且样式的实例是静态的,即“缓存”并在使用此样式的所有实例之间共享。
但是,这个实例(作为所有/大多数 UI 元素)是一个 DispatcherObject,只能在最初创建它的线程中使用。因此,当我第二次打开一个窗口(在它自己的新 UI 线程上)时,它会访问之前在不同线程上构建的相同静态 Style 资源,我得到以下异常:
System.Windows.Markup.XamlParseException
HResult=0x80131501
Message='Set property 'System.Windows.FrameworkElement.Style' threw an exception.' Line number '15' and line position '9'.
Source=PresentationFramework
StackTrace:
at System.Windows.Markup.XamlReader.RewrapException(Exception e, IXamlLineInfo lineInfo, Uri baseUri)
This exception was originally thrown at this call stack:
System.Windows.StyleHelper.ProcessInstanceValuesHelper(ref MS.Utility.ItemStructList<System.Windows.ChildValueLookup>, System.Windows.DependencyObject, int, System.Collections.Specialized.HybridDictionary, bool)
System.Windows.StyleHelper.ProcessInstanceValuesForChild(System.Windows.DependencyObject, System.Windows.DependencyObject, int, System.Collections.Specialized.HybridDictionary, bool, ref MS.Utility.FrugalStructList<System.Windows.ChildRecord>)
System.Windows.StyleHelper.DoStyleInvalidations(System.Windows.FrameworkElement, System.Windows.FrameworkContentElement, System.Windows.Style, System.Windows.Style)
System.Windows.StyleHelper.UpdateStyleCache(System.Windows.FrameworkElement, System.Windows.FrameworkContentElement, System.Windows.Style, System.Windows.Style, ref System.Windows.Style)
System.Windows.FrameworkElement.OnStyleChanged(System.Windows.DependencyObject, System.Windows.DependencyPropertyChangedEventArgs)
System.Windows.DependencyObject.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs)
System.Windows.FrameworkElement.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs)
System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs)
System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex, System.Windows.DependencyProperty, System.Windows.PropertyMetadata, System.Windows.EffectiveValueEntry, ref System.Windows.EffectiveValueEntry, bool, bool, System.Windows.OperationType)
System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty, object, System.Windows.PropertyMetadata, bool, bool, System.Windows.OperationType, bool)
...
[Call Stack Truncated]
Inner Exception 1:
InvalidOperationException: Cannot access Freezable 'System.Windows.Shell.WindowChrome' across threads because it cannot be frozen.
如果我删除 Style 属性,一切都很好。
我也尝试使用DynamicResource,但引用的样式引用了我无法控制的其他静态资源,并导致“进一步”出现同样的问题。
这可以解决吗?
(*) 是的,我知道:长时间运行的操作不应该由 UI 线程处理,但是改变它需要太多的重构(目前)并且用户在这种情况发生时不要做任何事情,所以即使,如果操作外包给一个任务,我实际上会禁用 UI。
编辑 1: 所以带我去this post;我尝试在窗口声明中添加x:Shared="False",但没有帮助。
编辑 2:我还尝试按照here 的描述冻结样式资源,但没有帮助。
【问题讨论】:
标签: wpf multithreading xaml