I have a WPF application with a long-running task on the UI thread for which I would like to show a progress bar (*). Since the UI is busy, following this solution, I chose to open the window with the progress bars on a separate UI/STA-Thread.
Everything works fine - the first time I create the window. The problem is apparently that the window uses Style="{StaticResource CustomWindowStyle}"
and the instance of the style is static, i.e. "cached" and shared between all instances using this style.
But, this instance is (as all/most UI elements) a DispatcherObject
that may only be used from the thread it was initially created on. So, when I open a window a second time (on it's own, new UI thread), it accesses the same static Style
resource that was previously built on a different thread and I get the following exception:
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.
If I remove the Style
attribute, everything is fine.
I also tried using DynamicResource
, but the referenced style references other static resources that I have no control over and cause the same problem "further down the line".
Can this be resolved?
(*) Yes, I know: long-running operations should not be processed by the UI thread, but changing that would require too much refactoring (for right now) and the user is not to do anything while this happens so even, if the operation was outsourced to a task, I would practically disable the UI anyway.
EDIT 1: SO lead me to this post; I tried adding x:Shared="False"
to the window declaration, but it didn't help.
EDIT 2: I also tried freezing the style resource as described here, but it didn't help.