在多线程 WPF 应用程序中创建 LinearGradientBrush 时出现 InvalidOperationException

发布于 2024-09-28 18:51:34 字数 3478 浏览 5 评论 0原文

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 消息=调用线程无法访问此对象,因为不同的线程拥有它。 来源=WindowsBase 堆栈跟踪: 在 System.Windows.Threading.Dispatcher.VerifyAccess() 在 System.Windows.Threading.DispatcherObject.VerifyAccess() 在 System.Windows.Freezable.ReadPreamble() 在 System.Windows.Media.GradientStopCollection.OnInheritanceContextChangedCore(EventArgs args) 在 System.Windows.DependencyObject.OnInheritanceContextChanged(EventArgs args) 在 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 操作类型) 在System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp,对象值,PropertyMetadata元数据,布尔coerceWithDeferredReference,OperationType操作类型,布尔isInternal) 在 System.Windows.DependencyObject.SetValueInternal(DependencyProperty dp,对象值) 在 System.Windows.Media.LinearGradientBrush..ctor(GradientStopCollection 梯度StopCollection) 在 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 提供给视图模型的构造函数?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦罢 2024-10-05 18:51:34

好的,看起来将 _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()); 工作正常,没有抛出异常。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文