Создать завершенную задачу

Я хочу создать завершенный Task (not Task<T>). Есть ли что-то встроенное в .NET для этого?

Связанный с этим вопрос: Создать завершенную задачу <T>

Ответ 1

самая новая версия .Net(v4.6) добавляет именно это, встроенный Task.CompletedTask:

Task completedTask = Task.CompletedTask;

Это свойство реализовано как single-lock без блокировки, поэтому вы почти всегда будете использовать одну и ту же завершенную задачу.

Ответ 2

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;
}

Ответ 3

Мой предпочтительный метод для этого - вызвать 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() без аргументов.

Ответ 4

Я бы использовал Task.Delay(0). Внутри он возвращает кешированный экземпляр завершенного Task<T>. Это то, что предлагает текущий ответ, так как теперь вам не нужно кэшировать экземпляр самостоятельно, и у вас нет каких-либо нечетких значений мусора в вашем коде.

Возможно, вы думаете, что можете использовать Task.Yield() вместо этого, но получается, что результат Task.Yield() не является подтипом Task, тогда как результатом Task.Delay(0) является. Это одно из тонких различий между ними.

Ответ 5

Вы можете использовать Task.FromResult (в .NET 4.5), чтобы вернуть завершенный Task<T>.

Если вам нужен не общий Task, вы всегда можете использовать Task.FromResult(0) или аналогичный, поскольку Task<T> является подклассом Task.

Ответ 6

Для .Net 4.6 и выше используйте

return Task.CompletedTask;

Для более низкой версии вы можете использовать

return new Task(() => { });

Ответ 8

Как насчет:

#pragma warning disable 1998
    public async Task emptyTask() {
    }
#pragma warning restore 1998

Вы можете оставить предупреждение, если не возражаете.