C#并行编程:修改xDocument

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


如果你有8个CPU核心,并且在8个不同的线程上运行8个实例,那么让方法内部的循环并行运行将不会提高性能。 - Yacoub Massad
真的吗?为什么?如果我在处理地址的同时并行处理日期,不应该会更快吗? - Ghassan Karwchan
你已经在不同的线程上运行多个DocumentProcessorService类的实例了,对吧?你的CPU核心数量是有限的。如果你运行16个线程,而你的CPU只有8个核心,那么每2个线程将共享一个核心。这意味着当其中一个线程正在运行时,另一个线程必须等待。 - Yacoub Massad
请看这个问题 - Yacoub Massad
如果你有几个吉字节大小的文件,你应该重新考虑你的设计。 - George Polevoy
显示剩余3条评论
2个回答

4

从XElement文档中可以看到:

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

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

另一个问题是,在相同数据上分叉操作类型是不切实际的。

这样做就不具备可扩展性了。

可能没有足够的操作类型来为每个CPU核心分叉,而且一种类型可能比另一种更快地完成。争用也很高。

如果您的文档包含一组类似方案的高级元素,则可以并行处理其副本,然后将旧元素替换为新元素。

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

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

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

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

这看起来非常棒。 我很兴奋地想试试。 非常感谢。 我会让您知道结果的。 - Ghassan Karwchan

1
< p >多个线程可以同时修改XDocument实例吗?是的,没有任何明确阻止线程进行更改(与WinForms / WPF中的UI操作不同)。< / p> < p >但由于XDocument类型不是线程安全的类,因此结果是完全不可预测的。< / p> < p >正确的实现应该防止对同一个XDocument的并行访问(即在访问操作周围使用lock),只要访问是串行化的,您就可以从任何线程更改它。< / p>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接