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

Я реализую метод Task<Result> StartSomeTask() и знаю результат уже до вызова метода. Как создать Задача <T> , которая уже завершена?

Это то, что я сейчас делаю:

private readonly Result theResult = new Result();

public override Task<Result> StartSomeTask()
{
    var task = new Task<Result>(() => theResult);
    task.RunSynchronously(CurrentThreadTaskScheduler.CurrentThread);
    return task;
}

Есть ли лучшее решение?

Ответ 1

private readonly Result theResult = new Result();

public override Task<Result> StartSomeTask()
{
    var taskSource = new TaskCompletionSource<Result>();
    taskSource.SetResult(theResult);
    return taskSource.Task;
}

Ответ 2

При настройке .NET 4.5 вы можете использовать Task.FromResult:

public static Task<TResult> FromResult<TResult>(TResult result);

Чтобы создать неудачную задачу, используйте Task.FromException:

public static Task FromException(Exception exception);
public static Task<TResult> FromException<TResult>(Exception exception);

.NET 4.6 добавляет Task.CompletedTask, если вам нужен не общий Task.

public static Task CompletedTask { get; }

Обходные пути для старых версий .NET:

  • При настройке .NET 4.0 с Async Targetting Pack (или AsyncCTP) вы можете использовать TaskEx.FromResult.

  • Чтобы получить не-общий Task до .NET 4.6, вы можете использовать тот факт, что Task<T> происходит от Task и просто вызывает Task.FromResult<object>(null) или Task.FromResult(0).

Ответ 3

Для задач без возвращаемого значения .NET 4.6 добавил Task.CompletedTask.

Он возвращает задачу, которая уже находится в TaskStatus.RanToCompletion. Он, вероятно, возвращает один и тот же экземпляр каждый раз, но документация предупреждает вас не рассчитывать на этот факт.

Ответ 4

Если вы используете Rx, альтернатива - Observable.Return(result).ToTask().

Ответ 5

Вызов Task.WhenAll без каких-либо параметров вернет завершенную задачу.

Task task = Task.WhenAll();