如何在Parallel.Foreach C#中使用内部并行循环?

时间:2019-01-23 23:56:27

标签: c#

我正在尝试优化代码,我想在Parallel.ForEach()内部调用Parallel.For。我不确定该怎么做。如果我确实发现结果不正确。我的代码将句子中的单词反了。

更改了for循环,它可以正常工作。

for(int i = word.Length-1; i> = 0; i-)

这是我失败的原始代码。

    public string Test()
    {
        string s = "Hello how are you";

        if (s.Length > 0)
        {
            StringBuilder reverseS = new StringBuilder(s.Length);
            string[] words = s.Split(' ');

            Parallel.ForEach(words, word =>
            {
                StringBuilder builder = new StringBuilder(word.Length);
                Parallel.For(0, word.Length - 1, i =>
                //for (int i = word.Length - 1; i >= 0; i--)
                {
                    builder.Append(word[i]);
                });
                reverseS.Append(builder);
                reverseS.Append(" ");
            });

            return reverseS.ToString();
        }

        else
        {
            return "";
        }
    }

哦,时代

1 个答案:

答案 0 :(得分:0)

我看到您必须反转字符,但保持单词位置。我不知道下面的代码与您的解决方案相比有多好,因此您可以进行一些性能测试。

这个想法是在主线程中反转数组中的单词,如果遇到一个很长的单词,则开始一个并行的单词。

private void Reverse()
{
    const int extremelyLongWordLength = 100000;

    var tasks = new List<Task>();
    var wordStart = 0;
    var arr = "Hello how are you".ToCharArray();
    for (var i = 0; i < arr.Length; i++)
    {
        if (arr[i] == ' ')
        {
            var wordEnd = i - 1;
            if (wordEnd - wordStart >= extremelyLongWordLength)
            {
                tasks.Add(ReverseWordAsTask(arr, wordStart, wordEnd));
            }
            else
            {
                ReverseWord(arr, wordStart, wordEnd);
            }

            wordStart = i + 1;
        }
    }

    if (wordStart != arr.Length - 1)
    {
        if (arr.Length - 1 - wordStart > extremelyLongWordLength)
        {
            tasks.Add(ReverseWordAsTask(arr, wordStart, arr.Length - 1));
        }
        else
        {
            ReverseWord(arr, wordStart, arr.Length - 1);
        }
    }

    Task.WaitAll(tasks.ToArray());

    var modifiedString = new string(arr);
}

private static Task ReverseWordAsTask(char[] arr, int start, int end)
{
    return Task.Run(() =>
    {
        var halfWordIndex = start + (end - start) / 2;
        for (var i = start; i < halfWordIndex; i++)
        {
            var temp = arr[i];
            var opposite = end - (i - start);
            arr[i] = arr[opposite];
            arr[opposite] = temp;
        }
    });
}

private static void ReverseWord(char[] arr, int start, int end)
{
    var halfWordIndex = start + (end - start) / 2;
    for (var i = start; i < halfWordIndex; i++)
    {
        var temp = arr[i];
        var opposite = end - (i - start);
        arr[i] = arr[opposite];
        arr[opposite] = temp;
    }
}