С# - Параллельно. Внутри и параллельно. Для того, что-то одно и то же?

И под "той же самой" я имею в виду, что эти две операции в основном выполняют одну и ту же работу, и она просто сводится к тому, что удобнее звонить на основе того, с чем вам приходится работать? (т.е. список делегатов или список вещей для итерации)? Я искал MSDN, StackOverflow и различные случайные статьи, но мне еще предстоит найти ясный ответ.

EDIT: Я должен был быть более ясным; Я спрашиваю, делают ли эти два метода одно и то же, потому что, если они этого не делают, я хотел бы понять, что было бы более эффективным.

Пример: у меня есть список из 500 ключевых значений. В настоящее время я использую цикл foreach, который выполняет итерацию по списку (последовательно) и выполняет работу для каждого элемента. Если я хочу использовать несколько ядер, следует ли вместо этого использовать Parallel.ForEach? допустим, для аргументов, что у меня был массив из 500 делегатов для этих 500 задач - будет ли сетевой эффект каким-либо другим вызовом Parallel.Invoke и предоставить ему список из 500 делегатов?

Большое спасибо заранее!

Ответ 1

Parallel.ForEach проходит через список элементов и может выполнять некоторую задачу по элементам массива.

например.

Parallel.ForEach(val, (array) => Sum(array));

Parallel.Invoke может ссылаться на многие функции параллельно.

например.

Parallel.Invoke(
() => doSum(array),
() => doAvg(array),
() => doMedian(array));

Как из приведенного выше примера, вы можете видеть, что они отличаются по функциональности. ForEach выполняет итерацию через List элементов и выполняет одну задачу для каждого элемента параллельно, а Invoke может выполнять много задач параллельно на одном элементе.

Ответ 2

Параллель .Invoke и Parallel.ForEach(при использовании для выполнения действий) работают одинаково, хотя да, в частности, требуется, чтобы коллекция была массивом. Рассмотрим следующий пример:

List<Action> actionsList = new List<Action>
            {
                () => Console.WriteLine("0"),
                () => Console.WriteLine("1"),
                () => Console.WriteLine("2"),
                () => Console.WriteLine("3"),
                () => Console.WriteLine("4"),
                () => Console.WriteLine("5"),
                () => Console.WriteLine("6"),
                () => Console.WriteLine("7"),
                () => Console.WriteLine("8"),
                () => Console.WriteLine("9"),
            };

            Parallel.ForEach<Action>(actionsList, ( o => o() ));

            Console.WriteLine();

            Action[] actionsArray = new Action[]
            {
                () => Console.WriteLine("0"),
                () => Console.WriteLine("1"),
                () => Console.WriteLine("2"),
                () => Console.WriteLine("3"),
                () => Console.WriteLine("4"),
                () => Console.WriteLine("5"),
                () => Console.WriteLine("6"),
                () => Console.WriteLine("7"),
                () => Console.WriteLine("8"),
                () => Console.WriteLine("9"),
            };

            Parallel.Invoke(actionsArray);

            Console.ReadKey();

Этот код производит этот вывод в одном прогоне. Он выводится, как правило, в другом порядке каждый раз.

0 5 1 6 2 7 3 8 4 9

0 1 2 4 5 6 7 8 9 3

Ответ 3

Я пытаюсь найти хороший способ его формулировки; но это не одно и то же.

Причина в том, что Invoke работает над Array of Action и ForEach работает над списком (в частности, IEnumerable) Action; Списки значительно отличаются от массивов в механике, хотя они выставляют одно и то же базовое поведение.

Я не могу сказать, что такое различие действительно связано с тем, что я не знаю, поэтому, пожалуйста, не принимайте это ответ (если вы действительно этого не хотите!), но я надеюсь, что это пробегает какую-то память о механизмах.

+1 для хорошего вопроса.

Изменить; Мне просто пришло в голову, что есть и другой ответ; Invoke может работать с динамическим списком Actions; но Foreach может работать с Generic IEnumerable of Actions и дает вам возможность использовать условную логику, Action by Action; поэтому вы можете проверить условие, прежде чем говорить Action.Invoke() в каждой итерации Foreach.