C#并行编程修改xDocument

C# parallel programming modifying xDocument

我以前从未在 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 进行并行计算?

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

但是由于 XDocument 类型不是线程安全的 class 结果是完全不可预测的。

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

来自 XElement 文档:

Thread Safety Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

这基本上意味着您不能并行修改 XDocument。

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

这种方式不可扩展。

可能没有足够的操作类型来为每个 CPU 核心进行分叉,并且一种类型的完成速度可能比另一种快得多。竞争也很大

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

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

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

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

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