Я хочу создать завершенный Task
(not Task<T>
). Есть ли что-то встроенное в .NET для этого?
Связанный с этим вопрос: Создать завершенную задачу <T>
Я хочу создать завершенный Task
(not Task<T>
). Есть ли что-то встроенное в .NET для этого?
Связанный с этим вопрос: Создать завершенную задачу <T>
самая новая версия .Net(v4.6) добавляет именно это, встроенный Task.CompletedTask:
Task completedTask = Task.CompletedTask;
Это свойство реализовано как single-lock без блокировки, поэтому вы почти всегда будете использовать одну и ту же завершенную задачу.
Task<T>
неявно преобразуется в Task
, поэтому просто получите завершенный Task<T>
(с любым T
и любым значением) и используйте его. Вы можете использовать что-то подобное, чтобы скрыть тот факт, что фактический результат есть где-то.
private static Task completedTask = Task.FromResult(false);
public static Task CompletedTask()
{
return completedTask;
}
Обратите внимание, что поскольку мы не показываем результат, и задача всегда завершена, мы можем кэшировать одну задачу и повторно ее использовать.
Если вы используете .NET 4.0 и не имеете FromResult
, вы можете создать свой собственный, используя TaskCompletionSource
:
public static Task<T> FromResult<T>(T value)
{
var tcs = new TaskCompletionSource<T>();
tcs.SetResult(value);
return tcs.Task;
}
Мой предпочтительный метод для этого - вызвать Task.WhenAll()
без аргументов. В документации MSDN указано, что "Если предоставленный массив/перечисляемый не содержит задач, возвращенная задача немедленно перейдет в состояние RanToCompletion до того, как будет возвращена вызывающему". Это похоже на то, что вы хотите.
Обновление: я нашел источник в Справочном источнике Microsoft; там вы можете увидеть, что Task.WhenAll содержит следующее:
return (tasks.Length == 0) ? // take shortcut if there are no tasks upon which to wait
Task.CompletedTask :
new WhenAllPromise(tasks);
Так что 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.CompletedTask;
Для более низкой версии вы можете использовать
return new Task(() => { });
Вы можете использовать Nito.AsyncEx.TaskConstants.Completed из большой библиотеки AsyncEx из Стивен Клири.
Как насчет:
#pragma warning disable 1998
public async Task emptyTask() {
}
#pragma warning restore 1998
Вы можете оставить предупреждение, если не возражаете.