Подтвердить что ты не робот

Улучшения многопоточности в .NET 4

Я слышал, что команда .NET 4 добавила новые классы в рамки, которые облегчают работу с потоками.

В основном возникает вопрос, каковы новые способы запуска многопоточных задач, добавленных в .NET 4, и для чего они предназначены для использования?

UPD:. Чтобы яснить, я не ищу ни одного способа запуска параллельных задач в .NET 4, я хочу узнать, какие новые добавлены, и если возможно, какая ситуация будет для каждого из них лучше всего подходит.

4b9b3361

Ответ 1

С отсутствием ответов я решил оценить ответы ниже с тем, что я узнал. Как заявил @Scott,.NET 4 добавила параллельную библиотеку задач, которая добавляет ряд нововведений, новые методы и подходы к parallelism.

  • Одна из первых вещей - методы Parallel.For и Parallel.ForEach, которые позволяют разработчику обрабатывать несколько элементов в нескольких потоках. Framework в этом случае будет решать, сколько потоков необходимо, а когда создавать новые потоки, а когда нет.
    Это очень простой и простой способ распараллеливать существующий код и повысить производительность.
  • Другим способом, несколько похожим на предыдущие подходы, является использование расширителей PLINQ. Они берут существующее перечисление и расширяют его с помощью параллельных расширений linq. Поэтому, если у вас есть существующий запрос linq, вы можете легко преобразовать его в PLINQ. Это означает, что все операции над перечислением PLINQ также будут использовать преимущества нескольких потоков, и фильтрация вашего списка объектов с помощью предложения .Where, например, будет выполняться в нескольких потоках сейчас!
  • Одним из самых больших нововведений в TPL является новый класс Task. В некотором смысле это может выглядеть как уже известный класс Thread, но он использует новый пул потоков в .NET 4 (который был значительно улучшен по сравнению с предыдущими версиями) и намного более функциональен, чем обычный Thread класс. Например, вы можете связать задачи, в которых задачи в середине цепочки будут запускаться только при завершении предыдущих. Примеры и подробное объяснение в screencast на Channel 9
  • Чтобы улучшить работу с классами Task, мы можем использовать BlockingCollection<>. Это прекрасно работает в ситуациях, когда у вас есть сценарий производителя-потребителя. У вас может быть несколько потоков, производящих некоторые объекты, которые затем будут потребляться и обрабатываться с помощью потребительских методов. Это можно легко распараллелить и контролировать с помощью задачи factory и блокировки. Полезный скринкаст с примерами из Channel 9
    Они также могут использовать разные классы хранения резервных копий (ConcurrentQueue, ConcurentStack, ConcurrentBag), которые все поточно-безопасны и отличаются по порядку и производительности элементов. Примеры и объяснения их в другом видео здесь
  • Добавлена ​​еще одна новая вещь (которая, вероятно, не является частью TPL, но помогает нам здесь) является классом CountdownEvent, который может помочь нам в "сценариях координации задач" (с). В принципе, мы можем дождаться завершения всех параллельных задач. Screencast с примером использования на Channel 9

Вы можете увидеть ряд видеороликов и видеороликов на канале 9, отмеченных "Parallel Computing"

Ответ 2

Да,.NET 4 добавила Task Parallel Library, которая на высоком уровне добавляет поддержку:

  • работающие параллельные петли с Parallel.For и Parallel.ForEach
  • создавать или запускать задачи с помощью Parallel.Invoke или Task class
  • PLINQ (параллельный LINQ to Objects)

Отвечая на обновление исходного вопроса...

TPL - это предпочтительный способ написания параллельных задач с использованием .NET 4. Вы все равно можете сами создавать элементы threadpool и выполнять все те же "ручные" методы потоков, которые вы могли раньше. Следует иметь в виду, что весь threadpool (и почти все связанные с потоком) был переписан, чтобы использовать TPL. Это означает, что даже если вы создаете элемент threadpool самостоятельно, вы все равно в конечном итоге используете TPL, даже если вы этого не знаете. Другая вещь, которую следует иметь в виду, заключается в том, что TPL намного оптимизирован и будет масштабироваться более соответствующим образом на основе количества доступных процессоров.

Что касается понимания того, в какой ситуации каждый из них лучше всего подходит, ответа на "серебряную пулю" нет. Если вы ранее ставили в очередь свой собственный элемент threadpool (или иначе делали что-то многопоточное), вы можете изменить эту часть своего кода, чтобы использовать TPL без каких-либо последствий.

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

Ответ 3

Строго говоря, это С# 4.0, а не новый класс, но события теперь имеют более умную форму блокировки, которая, если я понял правильное изменение, удаляет необходимость повторений кода блокировки, как показано ниже (взято из в этой статье от Jon Skeet ):

SomeEventHandler someEvent;
readonly object someEventLock = new object();

public event SomeEventHandler SomeEvent
{
    add
    {
        lock (someEventLock)
        {
            someEvent += value;
        }
    }
    remove
    {
        lock (someEventLock)
        {
            someEvent -= value;
        }
    }
}