Я хочу создать законченный Task
(не Task<T>
). Есть ли что-то встроенное в .NET для этого?
Связанный вопрос: Создать завершенную задачу <T>
c#
.net
async-await
task-parallel-library
Тимоти Шилдс
источник
источник
It seems like the answer I'm getting from everyone is that using a garbage value like this is the correct way. That there isn't a way to do this without the garbage value is disappointing -- oh well.
Как вы думаете, какие проблемы это имеет? Если вы кешируете одинTask
файл, тогда вся ваша программа занимает один дополнительный бит памяти. Это ничего . Кроме того, можно создать завершенную задачу, не делая этого, просто не будет ничего лучше.ValueTask
для завершенных задач (то есть для значений, которые у вас уже есть, так что код является по существу синхронным), что сэкономит вам распределение.Ответы:
В новейшей версии .Net (v4.6) добавлена только встроенная задача Task.CompletedTask :
Это свойство реализовано как синглтон без блокировки, поэтому вы почти всегда будете использовать одну и ту же завершенную задачу.
источник
Task.CompletedTask
все еще внутренний.Task<T>
неявно конвертируется вTask
, так что просто получите завершенноеTask<T>
(с любымT
и любым значением) и используйте его. Вы можете использовать что-то вроде этого, чтобы скрыть факт, что где-то есть фактический результат.Обратите внимание, что, поскольку мы не показываем результат, и задача всегда выполняется, мы можем кэшировать одну задачу и использовать ее повторно.
Если вы используете .NET 4.0, но у
FromResult
вас его нет, вы можете создать свой собственный, используяTaskCompletionSource
:источник
Мой предпочтительный метод для этого - вызывать
Task.WhenAll()
без аргументов. В документации MSDN указано, что «если предоставленный массив / перечислимый не содержит задач, возвращаемая задача немедленно перейдет в состояние RanToCompletion, прежде чем она будет возвращена вызывающей стороне». Это звучит как то, что вы хотите.Обновление: я нашел источник в Справочном источнике Microsoft ; там вы можете увидеть, что Task.WhenAll содержит следующее:
Таким образом, Task.CompletedTask действительно является внутренним, но он открывается, вызывая WhenAll () без аргументов.
источник
Я бы использовал
Task.Delay(0)
. Внутренне он возвращает кэшированный экземпляр завершенногоTask<T>
. Это именно то, что текущий ответ предлагает делать в любом случае, только теперь вам не нужно кэшировать экземпляр самостоятельно, и при этом в вашем коде нет никаких ненужных значений мусора.Вы можете подумать , вы можете использовать
Task.Yield()
вместо этого, но оказывается , что результат вTask.Yield()
это не подтипTask
, а результатTask.Delay(0)
есть. Это одно из тонких различий между ними.источник
Вы можете использовать Task.FromResult (в .NET 4.5) для возврата завершенного
Task<T>
.Если вам нужен неуниверсальный
Task
, вы всегда можете использоватьTask.FromResult(0)
или подобное, такTask<T>
как это подклассTask
.источник
Для .Net 4.6 и выше используйте
Для более низкой версии вы можете использовать
источник
return Task.Delay(0);
вместо?Вы можете использовать Nito.AsyncEx.TaskConstants.Completed из отличной библиотеки AsyncEx от Стивена Клири .
источник
Как насчет:
Вы можете не включать подавление предупреждений, если вы не против.
источник
async
прежнему создает весь аппарат конечного автомата, даже если вы его не используете, поэтому возврат пустого задания более эффективен для сценариев с ограниченными ресурсами.