在多线程 WPF 应用程序中创建 LinearGradientBrush 时出现 InvalidOperationException
在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好的,看起来将
_snazzyGradient
从static
字段移动到static
方法是有效的:我猜这是因为
GradientStop
不知何故,因为它是DependencyObject
的子级,就像我的UserControl
类一样,并且依赖项对象具有线程关联性。现在做var Brush = new LinearGradientBrush(getSnazzyGradient());
工作正常,没有抛出异常。Okay, looks like moving
_snazzyGradient
from being astatic
field to astatic
method worked:It's my guess that this is because of
GradientStop
somehow, since it's a child ofDependencyObject
as is myUserControl
class, and dependency objects have thread affinity. Now doingvar brush = new LinearGradientBrush(getSnazzyGradient());
works fine, no thrown exception.