【发布时间】:2016-12-08 16:04:17
【问题描述】:
我遇到了一个我不知道如何解决的问题,所以我开始认为我没有正确理解 BackgroundWorker。
我正在尝试使用 BackgroundWorker 来处理程序中的保存/加载功能,这意味着我希望工作人员调用我创建的序列化方法。
序列化方法采用 POCO 并 xml 序列化它。此 POCO 包含多个属性,其中之一是 Brush 类型。
public Brush ShapeColor{ get; set; }
我想序列化颜色,但由于无法序列化画笔,所以我做了一个辅助属性:
public Color StoreColor
{
get
{
g = ((Color)ShapeColor.GetValue(SolidColorBrush.ColorProperty)).G;
r = ((Color)ShapeColor.GetValue(SolidColorBrush.ColorProperty)).R;
b = ((Color)ShapeColor.GetValue(SolidColorBrush.ColorProperty)).B;
return Color.FromRgb(r, g, b);
}
set {}
}
不使用BackgroundWorker 也能正常工作。
但是一旦我尝试在doWork 方法中对序列化方法进行方法调用,就会抛出异常:
调用线程无法访问此对象,因为另一个线程拥有它。
关于这些:
g = ((Color)ShapeColor.GetValue(SolidColorBrush.ColorProperty)).G;
r = ((Color)ShapeColor.GetValue(SolidColorBrush.ColorProperty)).R;
b = ((Color)ShapeColor.GetValue(SolidColorBrush.ColorProperty)).B;
我的理解是,通过使用BackgroundWorker 从另一个线程而不是 UI 线程调用序列化方法,我违反了工作人员无法访问 UI 元素的规则。
老实说,我不太清楚如何提出我的问题,但我不可能只从工人那里序列化这些 POCO 吗?和ShapeColor是刷子有关系吗?
提前感谢我的错误解释:)
编辑:发布 xml 序列化方法。
public static void convertToXML<T>(T objectToSave, string path) where T : new()
{
StreamWriter streamWriter = null;
try
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
streamWriter = new StreamWriter(path, false);
XmlWriterSettings settings = new XmlWriterSettings()
{
Indent = true,
OmitXmlDeclaration = true,
};
serializer.Serialize(streamWriter, objectToSave);
}
finally
{
// Close writer
if (streamWriter != null)
{
streamWriter.Close();
}
}
}
【问题讨论】:
-
在创建
ShapeColor以及在此处访问它时尝试检查Thread.CurrentThread.ManagedThreadId。 -
GDI 对象(如画笔)不仅仅是数据结构,它们与 UI 线程相关联。您不能并且不需要为此使用BGW。 BGW 已被弃用并且对于异步保存完全没有必要。您可以使用例如FileStream的异步方法来异步保存数据
-
请张贴您的序列化代码。您发布的代码不会导致问题,也无法修改以修复它
-
@PanagiotisKanavos 所以是的,我读了一些,发现听起来你有我的答案:) - 我将能够修改序列化代码以实现异步调用,因为 StreamWriter API 支持异步方法?然后就放弃整个 BGW 的想法 :)?所以每次我序列化某些东西时,序列化方法会负责在另一个线程中处理任务?
-
这是一个非常具体的 WPF 限制。有点笨拙,但它对扩展属性的线程安全采取了严肃的态度。您对此无能为力,您需要先在 UI 线程上准备好数据,然后再让工作线程保存它。不会让代码更漂亮。
标签: c# multithreading serialization backgroundworker