Ответ 1
Вероятно, самым важным отличием между параллельными расширениями и регулярной резьбой является поток управления.
Поток, созданный с помощью new Thread(...)
или ThreadPool.QueueUserWorkItem
, завершится в полностью неопределенный момент времени. Если вы напишете этот код:
ThreadPool.QueueUserWorkItem(() =>
{
Thread.Sleep(1000);
Console.WriteLine("Work Finished");
});
Console.WriteLine("Item Queued");
Текст Item Queued
появится сразу, а Work Finished
будет напечатан после примерно 1 секунды задержки.
С другой стороны, если вы пишете что-то подобное с помощью параллельных расширений:
Parallel.For(0, 10, i =>
{
Thread.Sleep(1000);
Console.WriteLine("Test {0}", i);
});
Console.WriteLine("Finished");
То, что вы увидите в этом случае, - это задержка в 1 секунду, прежде чем что-нибудь случится, затем множество сообщений "Test" в случайном порядке, а затем текст Finished
.
Другими словами, выполнение задач параллельно не влияет на поток программы. Он будет запускать различные задачи для разных потоков, чтобы их можно было выполнять на нескольких ядрах ЦП, чтобы улучшить общую пропускную способность программы, но, что касается типичного программиста, эти задачи на самом деле не выполняются в "фоновом режиме" "так как они были бы с потоком. Вам не нужно изменять структуру вашей программы или делать что-либо особенное, чтобы получать уведомления о завершении работы. У вас нет контроля над тем, что происходит внутри параллельного блока, но вы знаете, что блок не будет возвращать управление, пока все параллельные задачи не будут завершены.
Несмотря на то, что Parallel Extensions отлично подходят для этого, следует отметить, что PX бесполезны, когда вам действительно нужно запустить задачу в фоновом режиме, например, реализовать планировщик или делегировать рабочий поток, чтобы сохранить пользовательский интерфейс отзывчивый. Вам все равно нужно использовать потоки или асинхронные компоненты для них.