Does the Use of the "Async" Suffix in a Method Name Depend on Whether the 'Async' Modifier Is Used

Does the use of the Async suffix in a method name depend on whether the 'async' modifier is used?

I think the truth is ambiguous even from Microsoft documentation:

In Visual Studio 2012 and the .NET Framework 4.5, any method that is
attributed with the async keyword (Async in Visual Basic) is
considered an asynchronous method, and the C# and Visual Basic
compilers perform the necessary transformations to implement the
method asynchronously by using TAP. An asynchronous method should
return either a Task or a Task<TResult> object.

http://msdn.microsoft.com/en-us/library/hh873177(v=vs.110).aspx

That's not right already. Any method with async is asynchronous and then its saying it should return either a Task or Task<T> - which isn't right for methods at the top of a call stack, Button_Click for example, or async void.

Of course, you have to consider what is the point of the convention?

You could say that the Async suffix convention is to communicate to the API user that the method is awaitable. For a method to be awaitable, it must return Task for a void, or Task<T> for a value-returning method, which means only the latter can be suffixed with Async.

Or you might say that the Async suffix convention is to communicate that the method can return immediately, relinquishing the current thread to perform other work and potentially causing races.

This Microsoft doc quote says:

By convention, you append "Async" to the names of methods that have an
Async or async modifier.

Content now only available via the Wayback Machine

Which doesn't even mention that your own asynchronous methods returning Task need the Async suffix, which I think we all agree they do.


So the answer to this question could be: both. In both cases, you need to append Async to methods with async keyword and that return Task or Task<T>.


I'm going to ask Stephen Toub to clarify the situation.

Update

So I did. And here's what our good man wrote:

If a public method is Task-returning and is asynchronous in nature (as
opposed to a method that is known to always execute synchronously to
completion but still returns a Task for some reason), it should have
an “Async” suffix. That’s the guideline. The primary goal here with
the naming is to make it very obvious to a consumer of the
functionality that the method being invoked will likely not complete
all of its work synchronously; it of course also helps with the case
where functionality is exposed with both synchronous and asynchronous
methods such that you need a name difference to distinguish them. How
the method achieves its asynchronous implementation is immaterial to
the naming: whether async/await is used to garner the compiler’s help,
or whether types and methods from System.Threading.Tasks are used
directly (e.g. TaskCompletionSource) doesn’t really matter, as that
doesn’t affect the method’s signature as far as a consumer of the
method is concerned.

Of course, there are always exceptions to a
guideline. The most notable one in the case of naming would be cases
where an entire type’s raison d’etre is to provide async-focused
functionality, in which case having Async on every method would be
overkill, e.g. the methods on Task itself that produce other Tasks.

As for void-returning asynchronous methods, it’s not desirable to have
those in public surface area, since the caller has no good way of
knowing when the asynchronous work has completed. If you must expose
a void-returning asynchronous method publicly, though, you likely do
want to have a name that conveys that asynchronous work is being
initiated, and you could use the “Async” suffix here if it made sense.
Given how rare this case should be, I’d argue it’s really a
case-by-case kind of decision.

I hope that helps, Steve

The succinct guidance from Stephen’s opening sentence is clear enough. It excludes async void because it is unusual to want to create a public API with such a design since the correct way to implement an asynchronous void is to return a plain Task instance and let the compiler to its magic. However, if you did want a public async void, then appending Async is advised. Other top-of-stack async void methods such as event handlers are usually not public and don’t matter/qualify.

For me, it tells me that if I find myself wondering about suffixing Async on an async void, I probably should turn it into an async Task so that callers can await it, then append Async.

Is it useful to mark a method async when it only awaits at the return statement?

doesn't this mean that method is basically synchronous

No. It's asynchronous. You're probably thinking of sequential (progressing from one thing to the next), not synchronous (blocking the current thread). An await will pause the method (sequentially) but not block the thread (asynchronously). For more information, see my async intro.

without the async modifier

While you could elide the async/await keywords, I would recommend that you do not. This is because // some more code here may throw an exception. I cover this and other considerations in my blog post on eliding async and await.

and the suffix Async?

No, that suffix is appropriate for any method that returns an awaitable (e.g., Task). So, even if you elide the async and await, it's still returning a task that should be awaited, so it should still have the Async suffix.

You can think of it this way: the Async suffix is part of the API interface. The async keyword is an implementation detail. They often go together, but not always.

Is the Async suffix required in the name of an async ASP.NET MVC 4 action?

No, this is not a requirement.

By convention, you append "Async" to the names of methods that have
an Async or async modifier.

You can ignore the convention where an event, base class, or interface
contract suggests a different name. For example, you shouldn’t rename
common event handlers, such as Button1_Click.

source: MSDN: Asynchronous Programming with Async and Await C# -> Naming Convetions

Always use the 'async' and 'await' keywords in asynchronous methods in a library?

Should I use async await in library?

It all depends. If you're going to take advantage of the asynchronous programming paradigm, then the answer is "yes," the async and await keywords are needed most of the time. More than likely, you will find yourself needing to use async/await. That is because in most situations it would be difficult to use only Task and Task<T> as you will more than likely need to reason about the results of the async operations that you invoke.

Additionally, based on your question it seems as though you may have some confusion about the keywords themselves and how they relate to the Task and Task<T> types. Allow me to clarify this for you.

The async keyword allows a method to use the await keyword. The best practice is to have all async methods return either Task or Task<T> unless you are unable to (for example, a button click event handler as you demonstrated above).

Methods that return Task or Task<T> represent asynchronous operations. When you are in a library it is suggested to always use .ConfigureAwait(false) for reasons detailed here. Additionally, I always point people to this detailed article on the subject.

To differentiate the two approaches in your question:

The method below returns a Task<SignResponse>. This is an async operation that represents the work to sign in. The method can be awaited by the caller to get SignResponse.

private Task<SignResponse> GetSignDataAsync(SigningRequestType request)
{
return _service.SignAsync(request);
}

Likewise, this version does the same thing...except that the async/await keywords are not needed. The reason they are not needed is that the method itself does not need to use SignResponse and therefore it could simply return Task<SignResponse> as shown above. And as you indicated in your question, there is indeed a penalty when you use the async/await keywords when they are not needed. Doing so adds an extra state machine step as the result is yielded, since its awaited.

private async Task<SignResponse> GetSignDataAsync(SigningRequestType request)
{
return await _service.SignAsync(request).ConfigureAwait(false);
}

Finally, if you needed to reason about the response, you could use the aforementioned keywords to do so like this:

private async Task<SignResponse> GetSignDataAsync(SigningRequestType request)
{
var result = await _service.SignAsync(request).ConfigureAwait(false);
if (result.SomeProperty == SomethingWeCareToCheck)
{
_log.Log("Wow, this was un-expected...");
}
return result;
}

How to convert a void synchronous method to async method?

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 (i.e., 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.

Interface naming convention for method returning Task

You should use XAsync even when there isn't an async modifier as long as the method represents a complete task based asynchronous operation.

To be technical about it, the passage you quoted tells you to add an Async when there is an async modifier but doesn't tell what to do when there isn't any.

The async modifier is really not a part of the method's signature and you could easily accomplish the exact same behavior without it. If you look at the Task-based Asynchronous Pattern you wouldn't find a reference to the specific async modifier, but to the more broad definition of an async method.

In the .Net framework itself, you can't even know which Async method actually uses the async modifier. A lot (if not most) return TaskCompletionSource.Task to allow you (as a user) to use async-await. For example, this is Stream.WriteAsync:

public virtual Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
// If cancellation was requested, bail early with an already completed task.
// Otherwise, return a task that represents the Begin/End methods.
return cancellationToken.IsCancellationRequested
? Task.FromCancellation(cancellationToken)
: BeginEndWriteAsync(buffer, offset, count);
}

How do I get a warning in Visual Studio when async methods don't end in 'Async'?

From Options,

  • Go to Text EditorBasicCode Style → Naming
  • Select Manage Specifications and Add New Specification
  • Select Method, tick all accessibility options and from Modifiers, select Async.
  • Give the title as Async Method and save
  • Now get into Manage Naming Styles and add New Style. Add Async as suffix and give it a name as AsyncSuffix, and then save
  • Now press the plus sign and create new naming. Select specification as Async Method, select required Style as AsyncPostfix and Severity as Suggestor.
  • Click OK and save

Sample Image

Sample Image

Sample Image

Task with Async signature vs no-signature

It does not matter regarding the behavior of the function if you add the "Async" suffix or not.

It does matter regarding the perception of your API by clients.

This naming convention is broadly adopted, so you do yourself and others a favor using it.

BTW:
If that API in question already contains legacy async functions (non-TAP) that are named "xxxAsync", then it is recommended to use "xxxTaskAsync" instead.



Related Topics



Leave a reply



Submit