In a static
C# method, I do var brush = new LinearGradientBrush(_snazzyGradient);
, and this line throws an exception. _snazzyGradient
is defined as follows:
private static readonly GradientStopCollection _snazzyGradient =
new GradientStopCollection
{
new GradientStop((Color)ColorConverter.ConvertFromString("#DBF3FF"), 0.0),
new GradientStop((Color)ColorConverter.ConvertFromString("#A3CCE0"), 1.0)
};
The class that contains both the method and _snazzyGradient
implements INotifyPropertyChanged
, if it matters, and is used as a view model. The static method that uses _snazzyGradient
gets called in a constructor for the class. In a UserControl
class, I set a dependency property's value to be a new instance of that view model class, using the constructor that references _snazzyGradient
.
When I'm debugging my app, at the var brush = new LinearGradientBrush(_snazzyGradient);
line, I get the following exception:
System.InvalidOperationException was caught Message=The calling thread cannot access this object because a different thread owns it. Source=WindowsBase StackTrace: at System.Windows.Threading.Dispatcher.VerifyAccess() at System.Windows.Threading.DispatcherObject.VerifyAccess() at System.Windows.Freezable.ReadPreamble() at System.Windows.Media.GradientStopCollection.OnInheritanceContextChangedCore(EventArgs args) at System.Windows.DependencyObject.OnInheritanceContextChanged(EventArgs args) at System.Windows.Freezable.AddInheritanceContext(DependencyObject context, DependencyProperty property) at System.Windows.DependencyObject.ProvideSelfAsInheritanceContext(DependencyObject doValue, DependencyProperty dp) at System.Windows.DependencyObject.ProvideSelfAsInheritanceContext(Object value, DependencyProperty dp) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, OperationType operationType) at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, OperationType operationType, Boolean isInternal) at System.Windows.DependencyObject.SetValueInternal(DependencyProperty dp, Object value) at System.Windows.Media.LinearGradientBrush..ctor(GradientStopCollection gradientStopCollection) at LoadedTemplate.getBackgroundForTemplateValue(String fieldName) at LoadedTemplate..ctor(ParentViewModel viewModel, Template template) at Form.LoadTemplate(Template template) InnerException:
I've already changed the dependency property in my UserControl
to the following:
public ParentViewModel Data
{
get
{
return (ParentViewModel)Dispatcher.Invoke(
DispatcherPriority.Background,
(DispatcherOperationCallback)delegate
{
return GetValue(DataProperty);
},
DataProperty
);
}
set
{
Dispatcher.BeginInvoke(
DispatcherPriority.Background,
(SendOrPostCallback)delegate
{
SetValue(DataProperty, value);
},
value
);
}
}
My question is, how can I get rid of this InvalidOperationException
? It doesn't seem right to have to put a bunch of Dispatcher
thread-related calls in my view model. Should I not define _snazzyGradient
as a static field but perhaps have it returned from a static method? I don't know if that would help. I definitely want multi-threadedness because I don't want the GUI bogged down when necessary files are read/written, that sort of thing. Maybe my problem stems from using GradientStop
(inherits from DependencyObject
), etc. in a view model; perhaps those should be given to the view model's constructor from my UserControl
?