views:

20

answers:

1

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?

A: 

Okay, looks like moving _snazzyGradient from being a static field to a static method worked:

private static GradientStopCollection getSnazzyGradient()
{
    return new GradientStopCollection
    {
        new GradientStop((Color)ColorConverter.ConvertFromString("#DBF3FF"), 0.0),
        new GradientStop((Color)ColorConverter.ConvertFromString("#A3CCE0"), 1.0)
    };
}

It's my guess that this is because of GradientStop somehow, since it's a child of DependencyObject as is my UserControl class, and dependency objects have thread affinity. Now doing var brush = new LinearGradientBrush(getSnazzyGradient()); works fine, no thrown exception.

Sarah Vessels