So I have this method that has only synchronous operations:
public void Foo(){
//do something synchronously
if(x == 0)
return;
else if(x < 5):
//do something
return;
// do something extra
}
Due to some interface changes, that method has to be changed to asynchronous, despite having no async operations. And in order to have the async keyword, there must be an await
keyword within its body. Would an equivalent method of the originally synchronous method be:
public async Task FooAsync(){
//do something synchronously
if(x == 0)
await Task.CompletedTask;
else if(x < 5):
//do something
await Task.CompletedTask;
// do something extra
}
I'm not sure about this since the CompletedTask
property indicates that it is a successful operation, which isn't the case for all these conditionals.
EDIT: Resolved in comments. Just because a method is denoted with an "async" suffix it does not mean that it needs an async
modifier. The function would be written as shown below to adhere to interface changes:
public Task FooAsync(){
//do something synchronously
if(x == 0)
return Task.CompletedTask;
else if(x < 5):
//do something
return Task.CompletedTask;
// do something extra
return Task.CompletedTask;
}
As others have noted, a task-like return type is an asynchronous signature , whereas async
is an asynchronous implementation detail . It's entirely possible to have a Task
-returning method not be async
.
However, there is one important caveat: exceptions. When an asynchronous (ie, Task
-like-returning) method fails, the expected semantics is to capture the exception and place it on the returned task.
So, you wouldn't want to just return CompletedTask
; you'd also want to capture exceptions and use Task.FromException
:
public Task FooAsync()
{
try
{
//do something synchronously
if(x == 0)
return Task.CompletedTask;
else if(x < 5):
//do something
return Task.CompletedTask;
// do something extra
return Task.CompletedTask;
}
catch (Exception ex)
{
return Task.FromException(ex);
}
}
At this point, there's rather a bit of boilerplate. You may prefer to use async
without await
, as such:
#pragma warning disable 1998
public async Task FooAsync()
#pragma warning restore 1998
{
//do something synchronously
if(x == 0)
return;
else if(x < 5):
//do something
return;
// do something extra
}
The problem with that approach is that you will get compiler warnings unless you include the ugly pragmas to disable them. If you find yourself needing to do this in several places, I would recommend using some helper methods ( stolen from my AsyncEx library ):
public static class TaskHelper
{
#pragma warning disable 1998
public static async Task ExecuteAsTask(Action func)
#pragma warning restore 1998
{
func();
}
#pragma warning disable 1998
public static async Task<T> ExecuteAsTask<T>(Func<T> func)
#pragma warning restore 1998
{
return func();
}
}
used as such:
public Task FooAsync() => TaskHelper.ExecuteAsTask(() =>
{
//do something synchronously
if(x == 0)
return;
else if(x < 5):
//do something
return;
// do something extra
});
which allows you to wrap synchronous methods quickly and easily.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.