Создание обертки задачи вокруг существующего объекта

У меня есть метод, который возвращает задачу, для реализации которой может потребоваться или не понадобиться выполнить медленную операцию, чтобы получить результат. Я хотел бы просто обвести значение результата в задачу, которая помечена как синхронно завершена в случае, когда значение уже доступно. Сегодня у меня есть что-то вроде этого:

public Task<Foo> GetFooAsync(int key) {
  lock(this) {
    if(_Cache.ContainsKey(key) ) {
      Task<Foo> ret = new Task<Foo>(()=>_Cache[key]);
      ret.RunSynchronously();
      return ret;
    }
    else {
      return Task.Factory.StartNew<Foo>(SomethingSlow());
    }
  }
}

Существует ли более простой способ сделать это, что не требует от меня задания задачи с делегатом, когда я уже знаю результат?

Ответ 1

Вы можете использовать TaskCompletionSource<TResult>:

var tcs = new TaskCompletionSource<Foo>();
tcs.SetResult(_Cache[key]);
return tcs.Task;

(Обратите внимание, что если _Cache является Dictionary<TKey, TValue>, вы можете использовать TryGetValue, чтобы сделать его единственным поиском.)

Ответ 2

Начиная с .NET 4.5, вы можете использовать статический метод Task.FromResult<T>() именно для этой цели:

return Task.FromResult(_Cache[key]);

Ответ 3

Если у вас есть синхронная версия метода, который возвращает результат, вы можете сделать следующее

Task<String>(()=> Hello(Name));

Метод hello будет выглядеть ниже.

public String Hello(String Name)
{
   return "Hello " + Name;
}