Reputation: 3283
I have a async method returning a task. Do I need to return anything in the following situation?
public async Task UpdateProductSpecificationsAsync()
{
await _productRepository.UpdateProductSpecificationsAsync(); //Takes long time to execute
}
Is the following code examples equivalent to each other?
public Task UpdateProductSpecifications()
{
_productRepository.UpdateProductSpecifications(); //Takes long time to execute
return Task.FromResult(0);
}
public Task UpdateProductSpecifications()
{
_productRepository.UpdateProductSpecifications(); //Takes long time to execute
return Task.CompletedTask;
}
Is there any situation where I should await a Task.TaskCompleted
?
Upvotes: 0
Views: 1235
Reputation: 70701
I have a async method returning a task. Do I need to return anything in the following situation?
An async Task
method is equivalent to a non-async void
method. And like a non-async void
method, an async Task
method can't return anything.
That said, your example seems odd. If all you're going to do in the method is await some other async method, you should not bother with the async
/await
at all. Just return the Task
directly:
public Task UpdateProductSpecificationsAsync()
{
return _productRepository.UpdateProductSpecificationsAsync();
}
Is the following code examples equivalent to each other?
Define "equivalent". To me, they are definitely not equivalent. The first creates a new Task<int>
object, and returns that object as a Task
. Calling code would have to cast it back to Task<int>
to see the result value.
The second returns the static Task.CompletedTask
property value, which is a singleton object, allocated only once per process. There is no result value for the caller to read.
The caller would have to go to extra work to directly observe those differences, but at the very least, returning a reference to a singleton object is more efficient than creating a new object every time. Whether this is significant or not depends, of course, on how often you call the method.
All that said, I don't understand why in that scenario, you wouldn't implement it like this (assuming there's no truly asynchronous version of the _productRepository
method):
public Task UpdateProductSpecificationsAsync()
{
return Task.Run(() => _productRepository.UpdateProductSpecifications());
}
Then you'd get actual asynchronous behavior, which is what the caller would typically expect. Your versions force the caller to wait in spite of the method looking like it's asynchronous. IMHO, it's a very bad idea to write code that lies.
Is there any situation where I should await a
Task.TaskCompleted
[sic]?
You mean directly? Or by code that doesn't know it's been handed the Task.CompletedTask
reference? I'm going to assume the former, because it's unreasonable to expect the latter to have any idea that's what it's doing.
That seems like an overly broad question to me. Any situation? That's open to interpretation.
That said, I would say "no" to that question. What would the point of awaiting something you know is already completed? The await
won't yield back to the caller, because the awaitable is already completed. It seems like a waste to me.
I can imagine scenarios where one awaits a Task.CompletedTask
in order to achieve some other desired side-effect. I've seen weirder things than that in production code. But I wouldn't recommend it. Whatever hypothetical side-effect we'd be talking about, I'm sure it's not a documented side-effect, so one would be relying on undocumented implementation details that could change in the future.
Don't write fragile code. Write code that relies only on documented behavior, and only does things that make obvious sense. (And the corollary: if you break that rule, at the very least write a very detailed comment explaining why you wrote weird, fragile code.)
Upvotes: 4