C#多线程合并大量XML文档

时间:2013-12-18 12:01:37

标签: c# multithreading design-patterns merge parallel-processing

我有一些合并XML文档的代码。它可以根据需要合并尽可能多的文档,但一旦数字开始增加就会变得有点慢。

    private string MergeList(List<string> documents)
    {
        string result = string.Empty;

        for (int i = 0; i < documents.Count; i++)
        {
            switch (i)
            {
                case 0: // Do nothing on first elapse
                    break;
                case 1: // Use first and second
                    result = Merge(documents[0], documents[i]);
                    break;
                default: // Now just keep merging until no more documents in list
                    result = Merge(result,documents[i]);
                    break;
            }
        }

        return result;
    } 

有多聪明的方法来做多线程吗?我需要的只是将所有文档合并到同一个字符串中。它们合并的顺序无关紧要。

我可以想象必须有某种模式才能做到这一点?

3 个答案:

答案 0 :(得分:2)

为简单起见,假设你有一些Merging功能(这里只是连接,你当然可以在这里进行XML处理等):

public static string Merge(string a, string b)
{
    return a + b;
}

您可以通过将输入集合拆分为两个并递归合并它们来通过递归创建一组Task<>。它可以被视为创建Tasks

等待图表
public static async Task<string> MergeRecursive(IEnumerable<string> strings)
{
    if (strings.Count() == 1)
        return strings.First();
    // Here we make a real merging
    if (strings.Count() == 2)
        return Merge(strings.First(), strings.Last());

    var parts = strings.Select((s, i) => new { s, i })
                       .GroupBy(g => g.i % 2, g => g.s, (k, v) => v)
                       .ToList();
    var results = await Task.WhenAll(parts.Select(p => Task.Run(() => MergeRecursive(p))));
    return await MergeRecursive(results);
}

然后你可以得到结果:

List<string> documents = new List<string>();
for (int i = 0; i < 100000; ++i)
    documents.Add(i.ToString("X"));

var merge = MergeRecursive(documents).Result;    

对于这种情况,Concurrency Visualizer显示了5个并行执行合并的CLR线程。

答案 1 :(得分:0)

一种简单的方法是将List<string>个文档设置为全局并添加BackgroundWorker并将事件DoWork设置为将文档和事件RunWorkCompleted合并到的函数该计划结束。

答案 2 :(得分:0)

如果您所做的只是将字符串连接在一起,那么多线程可能是过度的。相反,使用StringBuffer并预先计算大小以避免重新分配内存:

private string MergeList(List<string> documents)
{
  int size=0;

  foreach(var doc in documents)
  {
    size+=doc.Length;
  }

  StringBuffer buffer = new StringBuffer(size);

  foreach(var doc in documents)
  {
    buffer.append(doc);
  }

  return buffer.ToString();
}