C# 使用PLINQ或与保持原始顺序并行

C# 使用PLINQ或与保持原始顺序并行,c#,parallel-processing,plinq,C#,Parallel Processing,Plinq,我收集了大量的元素。我想为每个元素调用ToString并构建一个字符串。 我的第一个方法是放慢速度 string str = ""; list.ForEach( g => { string s = g.ToString(); if(s != "") str = str + g.ToString() + "\n"; }); 我尝试使用如下所示的并行类和PLIN

我收集了大量的元素。我想为每个元素调用ToString并构建一个字符串。 我的第一个方法是放慢速度

        string str = "";
        list.ForEach( g => {

            string s = g.ToString();
            if(s != "")
                str = str + g.ToString() + "\n";
        }); 
我尝试使用如下所示的并行类和PLINQ,但最终字符串中元素的顺序与原始字符串不同

平行的

        System.Threading.Tasks.Parallel.ForEach(list, g => {

            string s = g.ToString();
            if(s != "")
                str = str + g.ToString() + "\n";
        });
普林克

如何提高性能并保持原有秩序?
谢谢

我认为在这里尝试使用并行不是正确的解决方案,使用更好的算法才是

目前,您的代码是(n2),因为每次串联都会创建一个全新的字符串,因此它必须将以前的整个字符串复制到新字符串中

但是,如果使用可变的
StringBuilder
而不是不可变的
string
,则可以从O(n)开始执行此操作。这样,您只需在现有的
StringBuilder
末尾追加,而无需复制任何内容

您还可以使用一种只用于将字符串连接在一起的特殊方法,以更少的代码实现相同的性能:
string.Join()


但可能有更好的解决方案:使用
StreamWriter
。例如,如果您想将结果字符串写入文件,这将是一个更好的解决方案,因为整个字符串根本不需要在内存中


并行性并不能神奇地解决所有性能问题。您需要考虑线程将要做什么,特别是如果您的代码中有一些共享数据(如
str
)。在您的例子中,您可以尝试使用并行性,但它不会那么简单,而且我不确定它是否真的会提高性能


它的工作原理是这样的:每个线程将在列表中获得一系列索引,并将它们连接起来。最后,主线程将把所有线程的结果连接在一起。但是没有内置的方法,所以您需要自己编写所有代码。(这是可行的,因为字符串连接是。)

AsOrdered()
只保留原始顺序的顺序。因此,如果ForEach之后的顺序不同,那么您需要在之后对其进行排序。我不知道如何保持顺序(或者即使可能),但您应该使用StringBuilder,而不是串联字符串。更改为使用StringBuilder,而无需并行,从而解决了问题。谢谢大家
        string str = "";
        list.AsParallel().AsOrdered().ForAll( g => {

            string s = g.ToString();
            if(s != "")
                str = str + g.ToString() + "\n";
        });