问题
I have a method which returns a Task where the implementation may or may not need to perform a slow operation in order to retrieve the result. I would like to be able to simply wrap the result value into a Task which is marked as having completed synchronously in the case where the value is already available. Today I have something like this:
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());
}
}
}
Is there is simpler way to do this that doesn't require me to construct the task with a delegate when I already know the result?
回答1:
You could use a TaskCompletionSource<TResult>:
var tcs = new TaskCompletionSource<Foo>();
tcs.SetResult(_Cache[key]);
return tcs.Task;
(Note that if _Cache
is a Dictionary<TKey, TValue>
you could use TryGetValue
to make it a single lookup.)
回答2:
Beginning with .NET 4.5, you can use the Task.FromResult<T>() static method for exactly this purpose:
return Task.FromResult(_Cache[key]);
回答3:
If you have a synchronous version of the method that returns the result you can do the following
Task<String>(()=> Hello(Name));
The hello method would look like below.
public String Hello(String Name)
{
return "Hello " + Name;
}
来源:https://stackoverflow.com/questions/4692963/creating-a-task-wrapper-around-an-existing-object