Предложения по асинхронному вводу-выводу с параллельной библиотекой задач - PullRequest
5 голосов
/ 13 мая 2010

У меня есть высокопроизводительный код для передачи файлов, который я написал на C # с использованием идиомы модели асинхронного программирования (APM) (например, BeginRead / EndRead). Этот код читает файл с локального диска и записывает его в сокет.

Для обеспечения наилучшей производительности на современном оборудовании важно по возможности поддерживать более одной выдающейся операции ввода-вывода в полете. Таким образом, я размещаю несколько BeginRead операций над файлом, затем, когда одна из них завершается, я вызываю BeginSend в сокете, а когда она завершается, я делаю еще одну BeginRead в файле. Детали немного сложнее, но на высоком уровне это идея.

У меня работает код на основе APM, но за ним очень трудно следить, и, вероятно, есть небольшие ошибки параллелизма. Я хотел бы использовать TPL для этого вместо этого. Я подумал, что Task.Factory.FromAsync вот-вот сделает, но есть одна загвоздка.

Все сэмплы ввода / вывода, которые я видел (особенно класс StreamExtensions в дополнениях Parallel Extensions), предполагают одно чтение, а затем одну запись. Это не будет работать так, как мне нужно.

Я не могу использовать что-то простое, например Parallel.ForEach или расширение Extras Task.Factory.Iterate, потому что асинхронные задачи ввода-вывода не тратят много времени на рабочий поток, поэтому Parallel просто запускает другую задачу, в результате чего потенциально десятки или сотни ожидающих операций ввода-вывода; слишком много! Вы можете обойти это, Wait выполняя свои задачи, но это вызывает создание дескриптора события (объекта ядра) и блокировку ожидания для дескриптора ожидания задачи, который связывает рабочий поток. Моя реализация на основе APM позволяет избежать обеих этих вещей.

Я разыскивал разные способы держать несколько операций чтения / записи в полете, и мне удалось сделать это, используя продолжения, которые вызывают метод, который создает другую задачу, но он чувствует себя неловко и определенно не ' не чувствую себя идиоматическим TPL.

Кто-нибудь еще сталкивался с такой проблемой в TPL? Есть предложения?

1 Ответ

2 голосов
/ 13 мая 2010

Если вас беспокоит слишком большое количество потоков, вы можете просто установить ParallelOptions.MaxDegreeOfParallelism на допустимый номер в вашем вызове Parallel.ForEach.

...