C#并行编程修改xDocument

时间:2015-09-25 19:16:23

标签: c# c#-4.0 parallel-processing .net-4.0 parallel.foreach

我从未在c#中尝试过并行编程。 所以,在我跳入之前,我希望我能得到一个快速的答案,知道是否值得深入研究它。 我有.NET 4.0的C#WCF Web服务应用程序。 (如果并行编程有效,则可以升级到4.5)

所有服务都是REST服务。 有一项服务特别需要很长时间。 该服务正在处理和修改xml文档。 服务接受xml字符串作为输入,并返回修改后的xml文件。

该服务确实在不同的位置和不同的元素处理xml。 所以,我创建了一个继承自名为IDocumentProcessor的接口的类,我有一个列表

代码简要如下

interface IDocumentProcessor {
     void Process(XDocument doc);
}

public class DateProcessor : IDocumentProcessor
{
   public void Process(XDocument doc) {....};
}

public class CountryProcessor : IDocumentProcessor
{
   public void Process(XDocument doc) {....};
}


public class AddressProcessor : IDocumentProcessor
{
   public void Process(XDocument doc) {....};
}


public class AuthorProcessor : IDocumentProcessor
{
   public void Process(XDocument doc) {....};
}

....

Public class DocumentProcessorService
{
    public class ProcessDocument(string xmlFileAsString) 
    {
        var processorList = new List<IDocumentProcessor>{
            new DateProcessor();
            new CountryProcessor();
            new AddressProcessor();
            new AuthorProcessor();
        }

        var xDocument = XDocument.Parse(xmlFileAsString);
        processorList.forEach(x => x.Process(xDocument));
    }
}

所以我的快速问题,在我深入研究这个并行之前: 并行计算可以修改相同的xDocument对象(在不同的位置)

并且可以将此代码转换为使用.net 4.0进行并行计算吗?

2 个答案:

答案 0 :(得分:3)

来自XElement文档:

  

线程安全   此类型的任何公共静态(在Visual Basic中为Shared)成员都是线程安全的。不保证任何实例成员都是线程安全的。

它基本上意味着您无法并行修改XDocument。

另一个问题是,对同一数据的某种操作进行分叉是不切实际的。

这种方式不可扩展。

对于每个CPU内核,fork可能没有足够的操作类型,并且一种类型可能比另一种更快地完成。争论也很高。

如果您的文档包含类似方案的高级元素集合,您可以并行处理它们的副本,然后用新的副本替换旧的副本。

重新组装操作必须在一个线程中完成,如果选择正确的粒度级别,则不应太昂贵。

您基本上需要为每个要处理的XElement创建一个复制构造函数。

    var newElements = collectionElement.Elements().Select(el=>
    Process(new XElement(el))).AsParallel();

  var newCollection = new XElement("items", newElements);

答案 1 :(得分:0)

可以多个线程同时修改XDocument的实例 - 是的,没有明确停止线程进行更改(与WinForms / WPF中的UI操作不同)。 / p>

但由于XDocument类型不是线程安全类,因此结果完全不可预测。

正确的实现应该阻止对相同XDocument的并行访问(即使用lock访问操作),只要访问被序列化,您就可以从任何线程更改它。