Параллельная библиотека задач против Асинхронных рабочих процессов

StackOverflow https://stackoverflow.com/questions/1871168

Вопрос

У меня есть кое-что, написанное на c #, что выполняет параллельный код, интенсивно используя параллельную библиотеку Task (цепочки задач и будущих продолжений).

Сейчас я переношу это на F # и пытаюсь выяснить плюсы и минусы использования F # асинхронных рабочих процессов по сравнениюконструкции в TPL.Я склоняюсь к TPL, но я думаю, что это можно сделать в любом случае.

Есть ли у кого-нибудь советы и мудрость по написанию параллельных программ на F #, которыми можно поделиться?

Это было полезно?

Решение

Название в значительной степени суммирует разницу: асинхронный программирование против параллельный программирование.Но в F # вы можете смешивать и сочетать.

F # Асинхронные рабочие процессы

Асинхронные рабочие процессы F # полезны, когда вы хотите, чтобы код выполнялся асинхронно, то есть запускал задачу, а не ждал конечного результата.Наиболее распространенным использованием этого являются операции ввода-вывода.Когда ваш поток находится в цикле ожидания в ожидании завершения записи на ваш жесткий диск, это пустая трата ресурсов.

Если вы начали операцию записи асинхронно, вы можете приостановить поток и позже разбудить его аппаратным прерыванием.

Параллельная Библиотека задач

Библиотека Task Parallel в .NET 4.0 абстрагирует понятие задачи, например, декодирование MP3 или чтение некоторых результатов из базы данных.В этих ситуациях вы действительно хотите получить результат вычисления и в какой-то момент времени позже ожидаете результата операции.(Путем доступа к свойству .Result .)

Вы можете легко смешивать и сопоставлять эти концепции.Например, выполнение всех ваших операций ввода-вывода в объекте TPL Task.Для программиста вы абстрагировались от необходимости "разбираться" с этим дополнительным потоком, но под шумок вы впустую тратите ресурсы.

Подобно wise, вы можете создать серию асинхронных рабочих процессов F # и запускать их параллельно (Async.Параллельно), но тогда вам нужно дождаться конечного результата (Async.RunSynchronously).Это освобождает вас от необходимости явно запускать все задачи, но на самом деле вы просто выполняете вычисления параллельно.

По своему опыту я нахожу, что TPL более полезен, потому что обычно я хочу выполнять N операций параллельно.Однако рабочие процессы F # async идеальны, когда есть что-то, что происходит "за кулисами", например, реактивный агент или тип почтового ящика.(Вы отправляете чему-то сообщение, оно обрабатывает его и отправляет обратно.)

Надеюсь, это поможет.

Другие советы

В версии 4.0 я бы сказал:

  • Если ваша функция последовательна, используйте асинхронные рабочие процессы.Они просто лучше читаются.
  • Используйте TPL для всего остального.

Его также можно смешивать и сочетать.Они добавили поддержку запуска рабочего процесса в виде задачи и создания задач, которые следуют шаблону асинхронного начала / завершения с использованием TaskFactory.Из синхронизации, эквивалент TPL для Асинхронный.С самого начала или Async.BuildPrimitive.

let func() =
    let file = File.OpenRead("foo")
    let buffer = Array.zeroCreate 1024
    let task1 = Task.Factory.FromAsync(file.BeginRead(buffer, 0, buffer.Length, null, null), file.EndRead)
    task1.Start()

    let task2 = Async.StartAsTask(file.AsyncRead(1024))
    printfn "%d" task2.Result.Length

Также стоит отметить, что как среда выполнения асинхронных рабочих процессов, так и TPL собираются создать дополнительный примитив ядра (событие) и использовать WaitForMultipleObjects ( Формат ожидания множественных объектов ) отслеживать завершение ввода-вывода, а не использовать порты завершения и обратные вызовы.Это нежелательно в некоторых приложениях.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top