Поток данных (Task Parallel Library) и асинхронное ожидание

Допустим, я использую блоки потока данных в.NET. Утверждается, что "эта модель потока данных способствует программированию на основе акторов". Именно это я и хочу получить.

Однако если я обрабатываю сообщения от BufferBlock<T> и в обработчике сообщения я решаю использовать async/await, это прервет выполнение текущего шага и рабочего потока ожидаемой задачи.

Есть ли способ предотвратить одновременное выполнение в обработчике субъекта / сообщения здесь?

хорошо, если ожидаемая задача выполняется с использованием неблокирующих операций ввода-вывода с нативными обратными вызовами. Но я бы очень хотел убедиться, что любой код.NET выполняется только синхронно.

2 ответа

Решение

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

Если вы используете ActionBlock с asyncactionне устанавливайте его MaxDegreeOfParallelism (что означает значение по умолчанию 1) и свяжите его с BufferBlockтогда action будет выполняться для одного сообщения за раз, параллелизма не будет.

Если вы обрабатываете сообщения вручную, используя цикл вроде этого:

while (await bufferBlock.OutputAvailableAsync())
{
    var message = await bufferBlock.ReceiveAsync();
    await ProcessMessageAsync(message);
}

Затем сообщения будут обрабатываться по одному тоже.

Но в обоих случаях это не означает, что сообщение будет обработано одним потоком. Он может обрабатываться несколькими потоками, но не параллельно. Это потому что после awaitвыполнение может быть возобновлено в другом потоке, а не в том месте, где оно было приостановлено.

Если вы используете какой-то другой способ обработки сообщений (например, используя цикл выше, но опуская await до ProcessMessageAsync()), тогда несколько сообщений могут быть обработаны одновременно.

Вы неправильно поняли, что await делает. Он ничего не разветвляет, он просто ждет результата уже асинхронной операции.

Методы, отмеченные async Ключевое слово не становится автоматически асинхронным. Это только когда асинхронная операция встречается внутри async Метод, выполнение которого продолжается асинхронно. async Ключевое слово просто сообщает компилятору, где выполнение должно продолжаться после завершения асинхронной операции.

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

Другие вопросы по тегам