【问题标题】:InvalidOperationException when creating LinearGradientBrush in multi-threaded WPF app在多线程 WPF 应用程序中创建 LinearGradientBrush 时出现 InvalidOperationException
【发布时间】:2010-10-19 19:39:49
【问题描述】:

static C# 方法中,我执行var brush = new LinearGradientBrush(_snazzyGradient);,这行会引发异常。 _snazzyGradient 定义如下:

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

同时包含方法和_snazzyGradient 的类实现INotifyPropertyChanged(如果重要),并用作视图模型。使用_snazzyGradient 的静态方法在类的构造函数中被调用。在UserControl 类中,我使用引用_snazzyGradient 的构造函数将依赖属性的值设置为该视图模型类的新实例。

当我调试我的应用程序时,在 var brush = new LinearGradientBrush(_snazzyGradient); 行,我收到以下异常:

System.InvalidOperationException 被捕获 Message=调用线程无法访问此对象,因为不同的线程拥有它。 源=WindowsBase 堆栈跟踪: 在 System.Windows.Threading.Dispatcher.VerifyAccess() 在 System.Windows.Threading.DispatcherObject.VerifyAccess() 在 System.Windows.Freezable.ReadPreamble() 在 System.Windows.Media.GradientStopCollection.OnInheritanceContextChangedCore(EventArgs 参数) 在 System.Windows.DependencyObject.OnInheritanceContextChanged(EventArgs 参数) 在 System.Windows.Freezable.AddInheritanceContext(DependencyObject 上下文,DependencyProperty 属性) 在 System.Windows.DependencyObject.ProvideSelfAsInheritanceContext(DependencyObject doValue,DependencyProperty dp) 在 System.Windows.DependencyObject.ProvideSelfAsInheritanceContext(对象值,DependencyProperty dp) 在 System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex,DependencyProperty dp,PropertyMetadata 元数据,EffectiveValueEntry oldEntry,EffectiveValueEntry& newEntry,布尔 coerceWithDeferredReference,OperationType operationType) 在 System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp、对象值、PropertyMetadata 元数据、布尔 coerceWithDeferredReference、OperationType operationType、布尔 isInternal) 在 System.Windows.DependencyObject.SetValueInternal(DependencyProperty dp,对象值) 在 System.Windows.Media.LinearGradientBrush..ctor(GradientStopCollection gradientStopCollection) 在 LoadedTemplate.getBackgroundForTemplateValue(字符串字段名) 在 LoadedTemplate..ctor(ParentViewModel viewModel,模板模板) 在 Form.LoadTemplate(模板模板) 内部异常:

我已经将 UserControl 中的依赖属性更改为以下内容:

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
        );
    }
}

我的问题是,我怎样才能摆脱这个InvalidOperationException?在我的视图模型中放置一堆Dispatcher 线程相关的调用似乎是不对的。我不应该将_snazzyGradient 定义为静态字段,而是将其从静态方法返回吗?我不知道这是否会有所帮助。我绝对想要多线程,因为我不希望 GUI 在读/写必要的文件时陷入困境,诸如此类。也许我的问题源于在视图模型中使用GradientStop(继承自DependencyObject)等;也许这些应该从我的UserControl 提供给视图模型的构造函数?

【问题讨论】:

  • 不确定它是否适用于此,但在不同线程中使用它们时,您应该始终冻结您的画笔。当您这样做时,您永远不必担心线程问题。

标签: c# wpf multithreading mvvm invalidoperationexception


【解决方案1】:

好的,看起来将 _snazzyGradientstatic 字段移动到 static 方法有效:

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

我猜这是因为GradientStop 不知何故,因为它是DependencyObject 的子对象,就像我的UserControl 类一样,并且依赖对象具有线程亲和性。现在做var brush = new LinearGradientBrush(getSnazzyGradient()); 工作正常,没有抛出异常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多