Верно ли понимаю TPL и асинхронность?

Всем хорошей пятницы, знатоки!
Разбираюсь с TPL и асихронностью, хотелось бы проверить, правильно ли я понимаю некоторые моменты.
Пожалуйста, покритикуйте, желательно с объяснением.
Если вы знаете задачи/вопросы на понимание логики данной тематики, поделитесь ссылками, спасибо!

1. При использовнии Task совершенно необязательно задача в этом таске исполняется в новом потоке.
2. Такс выполняется в новом потоке, если асинхронный метод возвращает return Task.Run().
3. Асинхронные I/O операции не используют дополнительный поток.
4. Асинхронные CPU-bound операции выполняем в новом потоке. Они где-то же должны работать.
5. TaskCompletiotionSource<> служит для ручного создания тасков, чтобы оборачивать код, основанный на старых паттернах асинхронности. Например, есть асинхронная операция, основанная на event паттерне, мы подписываемся на событие завершения, по завершении события ставим результат Таска.
  • Вопрос задан
  • 687 просмотров
Решения вопроса 1
Nipheris
@Nipheris Куратор тега C#
1. Да, задача может исполниться где угодно. Более того, вы не поверите, но некоторые таски вообще могут нигде не исполняться, т.к. исполнять нечего (см. п. 5). Таск - это прежде всего абстракция значения, которое будет получено в будущем, и для получения которого возможно нужно что-то посчитать или просто подождать. См. futures and promises.
2. Ну не обязательно в новом потоке, может быть выполнится и в существующем потоке если в пуле потоков есть свободный.
3. Асинхронные операции ввода-вывода называются так потому, что выполняются через асинхронное API операционной системы. Нет никакого смысла использовать асинхронную операцию, но делать это в отдельном потоке созданном специально для этой операции. Потоки нужны прежде всего для того, чтобы эффективно нагружать исполнителей, т.е. процессоры (в том числе разные их ядра).
4. Можно в новом, можно в потоке из пула. Так или иначе, если операция предполагает именно расчёты, а не ожидание ввода/вывода, то безусловно это тот случай, когда имеет смысл переложить нагрузку на другой поток.
5. Если представлять таск как одну из сторон "трубы", по которой прилетит результат асинхронной операции, то Task - это принимающая сторона, а TaskCompletiotionSource - передающая (производящая результат) сторона. Когда вы создаёте таск из кода который нужно выполнить, этот код становится передающей стороной. Но Task абстрагирует любую асинхронную операцию, не только ту где нужно долго что-то считать. Возможно вам нужно дождаться одного байтика из сети, и операция будет считаться завершенной. Во всех тех случаях, когда вы хотите самостоятельно "произвести" результат для какого-то таска (а сам таск отдать "наружу" другому коду, например вернуть из функции), вы можете использовать TaskCompletionSource.
(Кстати, в C++ принимающая сторона называется future, а передающая (производящая) - promise. В JS принимающая сторона называется Promise, а передатчиком является функтор).
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы