首页 > 解决方案 > 如何在 Parallel.Foreach 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 "";
        }
    }

olleH woh 时代 uoy

标签: c#

解决方案


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

这个想法是在主线程中反转数组中的单词并在遇到一个很长的单词时启动一个并行的单词。

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;
    }
}

推荐阅读