Parallel.Foreach в двух циклах foreach - PullRequest
       7

Parallel.Foreach в двух циклах foreach

0 голосов
/ 20 сентября 2019

У меня есть список объектов, которые сгруппированы по одному столбцу, как показано ниже.

У меня есть миллионы записей, и это занимает более 30 минут.Как эффективно написать приведенный ниже код?

List<Voter> voterList = new List<Voter>();

IEnumerable<IGrouping<string, MemberInfo>> groupByLastName = infoList.GroupBy(info => info.LastName).Select(i => i);

foreach (List<MemberInfo> lastName in groupByLastName)
{
    foreach (MemberInfo member in lastName)
    {
        MemberInfo info = memberService.GetMemberDetails(member.FirstName);

        if (info.Age > 18)
        {
            voterList.Add(new Voter{
                VoterId = member.VoterId,
                Age = member.Age
            });
        }
    }
}

1 Ответ

3 голосов
/ 20 сентября 2019
  1. Использовать Parallel.ForEach

  2. Добавить ваш объект результата в потокобезопасную коллекцию.

Ниже приведены некоторыепсевдокод.Я не могу сказать, какие объекты у вас есть в вашем распоряжении, потому что ваш исходный пост использует «var» несколько раз.

 BlockingCollection<Voter> bc = new BlockingCollection<Voter>();


 Parallel.ForEach(myCollection, (e) => { 

     bc.Add(e);

 });

Поэтому я сначала собрал бы все ваши входные значения (в ваш wcf)

ICollection allTheInputLastNames = new List ();

IEnumerable<IGrouping<string, MemberInfo>> groupByLastName = infoList.GroupBy(info => info.LastName).Select(i => i);

foreach (List<MemberInfo> lastName in groupByLastName)
{
    foreach (MemberInfo member in lastName)
    {
       allTheInputLastNames.add(member.FirstName);
    }      
}

Теперь, поскольку у вас их так много, надеюсь, это выполняется довольно быстро.

Теперь, когда вы собрали все входные данные, вы хотите использовать Parallel.ForEach.

Я создал общий пример ниже.

Там, где у меня есть inputValues, у вас будут ваши allTheInputLastNames.

Где ясоздайте новый ResultObject, вы бы сделали вызов wcf-службы.

, и когда я делаю "StringLength% 2", вы бы сделали вашу информацию. Проверка времени.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MyApp.ParallelStuff
{
    public class ParallelExampleOne
    {

        public void ExampleOne()
        {

            ICollection<string> inputValues = new List<string>();

            for (int i = 1; i < 10000; i++)
            {
                inputValues.Add("MyValue" + Convert.ToString(i));
            }

            CancellationTokenSource ct = new CancellationTokenSource();

            BlockingCollection<ResultObject> finalItems = new BlockingCollection<ResultObject>();

            Parallel.ForEach(inputValues, (currentInputItem) =>
            {
                ResultObject ro = new ResultObject(currentInputItem.Length, currentInputItem);

                if (ro.StringLength % 2 == 0)
                {
                    finalItems.Add(ro);
                }

            });

            Console.WriteLine("ExampleOne.finalItems.Count={0}", finalItems.Count);
            string temp = string.Empty;
        }

        public void ExampleTwo()
        {

            ICollection<string> inputValues = new List<string>();
            for (int i = 1; i < 10000; i++)
            {
                inputValues.Add("MyValue" + Convert.ToString(i));
            }

            CancellationTokenSource ct = new CancellationTokenSource();

            BlockingCollection<ResultObject> finalItems = new BlockingCollection<ResultObject>();

            ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct.Token };

            ParallelLoopResult results = Parallel.ForEach(inputValues, options, currentInputValue =>
            {
                ResultObject ro = new ResultObject(currentInputValue.Length, currentInputValue);

                if (ro.StringLength % 2 == 0)
                {
                    finalItems.Add(ro);
                }

            });

            Console.WriteLine("ExampleTwo.finalItems.Count={0}", finalItems.Count);

            string temp = string.Empty;
        }



    internal class ResultObject
    {
        internal int StringLength { get; private set; }
        internal string OutputValue { get; private set; }

        public ResultObject(int stringLength, string inputValue)
        {
            this.StringLength = stringLength;
            this.OutputValue = inputValue + "MyOutputSuffix";
        }
    }

}

Также обратите вниманиекак вы можете прочитать мой код, потому что я не использовал «var» для объявлений переменных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...