In .NET, are async methods exclusively those with the async keyword? - c#

I've been learning about HttpClient (consuming API's in .NET in general), and therefore about async programming. I'm still pretty lost right now, so trying to clear some things up. One question I can't seem to find an answer to - are asynchronous methods implemented exclusively using the async keyword?
I understand that you could (theoretically) create synchronous methods using async programming, but how do you recognize that? For example, from this link and this example:
public string GetReleases(string url)
{
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add(RequestConstants.UserAgent, RequestConstants.UserAgentValue);
var response = httpClient.GetStringAsync(new Uri(url)).Result;
return response;
}
}
The author says:
For the simplicity’s sake, I implemented it synchronously
But how do I recognize it is synchronous? Is it solely because the method is not defined with async Task, for example:
public async Task<string> GetReleases(string url)
Does that mean that in this HttpClient tutorial, this example is also not asynchronous:
// GET: Student
public ActionResult Index()
{
IEnumerable<StudentViewModel> students = null;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:64189/api/");
//HTTP GET
var responseTask = client.GetAsync("student");
responseTask.Wait();
var result = responseTask.Result;
if (result.IsSuccessStatusCode)
{
var readTask = result.Content.ReadAsAsync<IList<StudentViewModel>>();
readTask.Wait();
students = readTask.Result;
}
else //web api sent error response
{
//log response status here..
students = Enumerable.Empty<StudentViewModel>();
ModelState.AddModelError(string.Empty, "Server error. Please contact administrator.");
}
}
return View(students);
}
So to sum up, my questions are:
Is async programming (in .NET), and async methods, implemented exclusively using async and void/Task/Task?
If not, how else, and if so, how do I recognize "true" asynchronous methods compared to synchronous methods implemented using asychronous principles (like the example above?)
Why then did the above examples use "sync through async", since from everything I've read everyone says to NEVER do that? Are they just bad examples, or for simplicity sake (even so, shouldn't "the correct way" > "simplicity"? Would it be ok to use this in situations where, e.g., I have very simple code and want to avoid threading/deadlock issues, since I'm not comfortable with async programming just yet?

how can I recognize truely async/sync methods?
You can't. Not really. You can spot methods that are potentially async, but little else can be learned without consulting documentation or the implementation of those methods.
So, you can examine a method's return type. If it's void, you don't know much. If it's Task, Task<T>, ValueTask<T> or any other awaitable type1, then the method may be asynchronous. But bear in mind, the method signature may be fixed because the type inherited the method from a base class or it's implementing an interface; So whilst the method has the potential to be async, the actual implementation of that method may be completely synchronous.
Or, the method may have the potential to be asynchronous but may have particular control flows which lead to it behaving synchronously2. These may be e.g. that if certain conditions are true, the method already has the answer, so it returns it straight away. Otherwise it goes off and does something async - as one example.
If the return type isn't awaitable and it's non-void, all you can actually reason about the method is that, at the point at which it returns, it's supplied some value for that return type3. There's no way to reason about any other work that may have been started by that method - only that if it's done something like that, it doesn't intend for you to be able to discover when that work has completed.
If you're looking at the implementation of a method and asking yourself "is this implementation async" then the important thing is to work out what this code makes happen after control is returned back to the caller.
When is control returned back to the caller?
When we hit a return
When we hit an await, maybe
When we hit an await, we only return control back to the caller4 if the awaitable that we're awaiting isn't complete yet. So we have to find out where that awaitable came from and, if it came from calling another method, we have to start again from scratch in considering what that method does.
If the method contains awaits then it's usually safest to say that it's potentially async - but bear in mind the above possibilities about already completed awaitables and early returns.
If it's not async/await, what else might it have done? Well, if it's working with Tasks, it may have created one or more of those tasks to represent it's ongoing work. It may have scheduled more code to run via ContinueWith.
If it's not working with Tasks directly, hasn't called something else that is potentially async, hasn't cause a new Thread to be created and isn't needlessly obfuscated, it's probably synchronous.
Would it be ok to use this in situations where, e.g., I have very simple code and want to avoid threading/deadlock issues, since I'm not comfortable with async programming just yet?
The sync over async patterns shown in the examples in your question are more prone to deadlocks than working with async/await. Why? Because they block the current thread waiting for other things to happen. But the current thread or resources that it has locked may be special - and the actual async tasks that it's invoked may need to gain access to that same thread/resource before they can complete. Classic deadlock.
1Awaitable is one of a number of places where C# uses "duck typing". If there's a method available (instance or extension) called GetAwaiter that returns a type with the right shape, it's awaitable. So despite the fact that you'll probably never see one, be aware that custom awaitables are possible in the language.
2"Hot path" optimizations come to mind.
3And out/ref parameters. Of course, if it has those it won't be an async method implemented via the async/await keywords but it may still have some asynchronous behaviour.
4If we've already yielded control back to the caller during an earlier await, we won't return control back to the caller at later awaits, but we'll be returning it to "something" that isn't our code.

If a method returns a Task or Task<T> (with exception to void in case of event handler) then it can be awaited and hence it can be asynchronous. async keyword is only an indication that it may await somewhere for another awaitable. Based on the control flow, async may return without actually awaiting anything.
Asynchronous programming is not a new thing, it has existed in many forms like callbacks, Invokes etc.
Examples you have provided are not using async await pattern properly. Microsoft has provided naming convention (Async Suffix) and Task<T>, Task as types for async programming. So if you see some method returning Task<T> or Task and Method name has suffix "Async" then you can consider it asynchronous. Although suffix thing is not required by compiler, it helps in differentiating it from its synchronous counterpart. (Read vs ReadAsync)
They are bad examples, those action should be marked as async and all the Async methods should be awaited for result. There can be an exception in some console program where main can't be async.
Please read Stephen Cleary blog on async await

An asynchronous method in C# can return void, Task or Task<T>, where void should be avoided in general because it cannot be awaited.
As a convention asynchronous methods should be called DoSomethingAsync()
The async keyword, however, is an implementation detail and does not belong to the API. This keyword is only required if you use an await in the method body. But that need not be the case. You could simply delegate to another asynchronous method, without the need to mark the method as async and using an await.
So 'true' asynchronous methods should be recognizable by the Async suffix of the method name, however, you can't be sure the implementor actually uses naturally asynchronous operations or even runs synchronously some parts or the whole method.
In the example he made the method synchronously by putting .Result at the end of GetStringAsync

Related

Returning from async methods

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?
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.)

When to use "async" instead of returning a new Task.Run task?

So here I have a function
static bool Login(SignupData sd)
{
bool success=false;
/*
Perform login-related actions here
*/
}
And there is another function
static Task<bool> LoginAsync(SignupData sd)
{
return Task.Run<bool>(()=>Login(sd));
}
Now, I've come across a rather different implementation of this pattern, where you would add the async keyword to a function which returns Task<TResult> (so that it ends up looking like: async Task<TResult> LoginAsync(SignupData sd)). In this case, even if you return TResult instead of a Task<TResult>, the program still compiles.
My question here is, which implementation should be prefered?
static Task<bool> LoginAsync(SignupData sd)
{
return Task.Run<bool>(()=>Login(sd));
}
OR this one?
async static Task<bool> LoginAsync(SignupData sd)
{
bool success=Login(sd);
return success;
}
You shouldn't be doing either. Asynchronous methods are useful if they can prevent threads from being blocked. In your case, your method doesn't avoid that, it always blocks a thread.
How to handle long blocking calls depends on the application. For UI applications, you want to use Task.Run to make sure you don't block the UI thread. For e.g. web applications, you don't want to use Task.Run, you want to just use the thread you've got already to prevent two threads from being used where one suffices.
Your asynchronous method cannot reliably know what works best for the caller, so shouldn't indicate through its API that it knows best. You should just have your synchronous method and let the caller decide.
That said, I would recommend looking for a way to create a LoginAsync implementation that's really asynchronous. If it loads data from a database, for instance, open the connection using OpenAsync, retrieve data using ExecuteReaderAsync. If it connects to a web service, connect using the asynchronous methods for whatever protocol you're using. If it logs in some other way, do whatever you need to make that asynchronous.
If you're taking that approach, the async and await keywords make perfect sense and can make such an implementation very easy to create.
While HVD is correct, I will dive into async in an attempt to describe its intended use.
The async keyword, and the accompanying await keyword is a shortcut method of implementing non blocking code patterns within your application. While it plays along perfectly with the rest of the Task Parallel Library (TPL), it isn't usually used quite the same. It's beauty is in the elegance of how the compiler weaves in the asynchronicity, and allows it to be handled without explicitly spinning off separate threads, which may or may not be what you want.
For Example, let's look at some code:
async static Task<bool> DoStuffAsync()
{
var otherAsyncResult = doOtherStuffAsync();
return await otherAsyncResult
}
See the await keyword? It says, return to the caller, continue on until we have the result you need. Don't block, don't use a new thread, but basically return with a promise of a result when ready (A Task). The calling code can then carry on and not worry about the result until later when we have it.
Usually this ends up requiring that your code becomes non-blocking the whole way down (async all the way as it were), and often this is a difficult transition to understand. However, if you can it is incredibly powerful.
The better way to handle your code would be to make the synchronous code call the async one, and wait on it. That way you would be async as much as possible. It is always best to force that level as high as possible in your application, all the way to the UI if possible.
Hope that made sense. The TPL is a huge topic, and Async/Await really adds some interesting ways of structuring your code.
https://msdn.microsoft.com/en-us/library/hh191443.aspx

C# - does Task.FromResult incur a heavy penalty?

I'm a bit new to async coding with C#, and have encountered a few places where methods I have to implement (either from an interface or part of an inherited service, or just suggested default convention) are marked async and expect a Task<T> return.
But I don't always have async code to run; I don't always have something that needs an await operator.
So my ad-hoc workaround is to just return await Task.FromResult({normal code}); to these kinds of methods, like this...
public async Task<JsonResult> Id() {
// if the user is not authenticated, simply return false
if (!User.Identity.IsAuthenticated || String.IsNullOrEmpty(User.Identity.Name))
return await Task.FromResult(Json(false));
return await Task.FromResult((Json(User?.FindFirst("users/id")?.Value ?? null)));
}
This does solve the compile time errors, but I was wondering if there is an inherit problem with doing this. If so, what are good methods for getting around things marked as async that I cannot change?
Rather than creating a Task, then adding a continuation to that task that does literally noting but wrap it in an identical Task, just return the first task that you created.
Since you have nothing to await, there is no reason for the method to be marked as async.
Considering the performance costs of FromResult is a pointless discussion. You need to create a task based on the result that you have, so that work needs to be done. Considering how expensive it is is irrelevant as you have no alternative options. You could try to create your own FromResult method if you think you can write one that'll perform better than Microsoft's version.
That said, no, it is not particularly expensive of an operation.

Is it advantageous to use ConfigureAwait(false) in a library that directly returns a Task from a call to another library?

Follow-up to this question. I have a library with many async methods that thinly wrap HttpClient. Effectively they just do some setup and directly return the Task returned from the HttpClient call:
public Task DoThingAsyc() {
// do some setup
return httpClient.DoThingAsync();
}
I'm pondering whether to add ConfigureAwait(false) to these calls. The prevailing wisdom seems to be "yes, always do that in libraries." But in this case, it would introduce some (perhaps negligible) overhead, because ConfigureAwait returns a ConfiguredTaskAwaitable which would need to be wrapped back into a Task in order to not change the method signature. Certainly not hard to code:
public async Task DoThingAsyc() {
// do some setup
return await httpClient.DoThingAsync().ConfigureAwait(false);
}
My question is, will the efficiency benefits of ConfigureAwait(false) likely outweigh the extra overhead introduced in this case? What example above would be considered the better practice?
No, don't do this.
Since you're not using await, you're not supposed to configure for it in advance. It's the responsibility of the caller of your library to do the ConfigureAwait call. And the caller may well want to call ConfigureAwait(true) instead of ConfigureAwait(false) - you don't know that.
Calling ConfigureAwait(false) in library code is best practice only when you await on it in the library.
In most cases, code like this:
async Task<Something> DoSomethingAsync()
{
return await DoSomethingElseAsync().ConfigureAwait(false);
}
Is equivalent to:
Task<Something> DoSomethingAsync()
{
return DoSomethingElseAsync();
}
if DoSomethingElseAsync respects the Task contract (for instance, if it returns a failed Task instead of throwing exceptions).
Creating an additional state machine for that is just adding one layer of wrapping code with no added value - it is better to simply return the Task directly.
In other words: you get no efficiency benefit whatsoever from doing this, quite the contrary.
No, ConfigureAwait as its name suggests, configures the await. If you don't need to await then you don't need to configure it.
There's no added value in adding async-await just to use ConfigureAwait as it only affects your method and not the calling method. If the caller needs to use ConfigureAwait they will do so themselves.
Having an async method instead of a simple Task-returning method is a valid choice for many reasons (e.g. exception handling), and it will require using ConfigureAwait but ConfigureAwait is not a good reason for doing that by itself.

c# 5 async as a sugar syntax (or not)?

So I was asking this question about async , and I thought that it it's just a sugar syntax for :
Task<..>...ContinueWith...
And finally inspect the Result property.
I even asked a question about it here and I was told :
But Today I was corrected by Jon Skeet
" It's a very long way from that".
So what are the core differences between those 2 approaches ?
It is adding a continuation - but manually constructing that continuation can be very painful, due to the need to carry around all the information about where we'd got to and what the local state is.
As a very simple example, I suggest you try to come up with the equivalent of this async method:
public static async Task<int> SumTwoOperationsAsync()
{
var firstTask = GetOperationOneAsync();
var secondTask = GetOperationTwoAsync();
return await firstTask + await secondTask;
}
// These are just examples - you don't need to translate them.
private async Task<int> GetOperationOneAsync()
{
await Task.Delay(500); // Just to simulate an operation taking time
return 10;
}
private async Task<int> GetOperationTwoAsync()
{
await Task.Delay(100); // Just to simulate an operation taking time
return 5;
}
Really try to come up with the equivalent of the first method. I think you'll find it takes quite a lot of code - especially if you actually want to get back to an appropriate thread each time. (Imagine code in that async method also modified a WPF UI, for example.) Oh, and make sure that if either of the tasks fails, your returned task fails too. (The async method will actually "miss" the failure of the second task if the first task also fails, but that's a relatively minor problem IMO.)
Next, work out how you'd need to change your code if you needed the equivalent of try/finally in the async method. Again, that'll make the non-async method more complicated. It can all be done, but it's a pain in the neck.
So yes, it's "just" syntactic sugar. So is foreach. So is a for loop (or any other kind of loop). In the case of async/await, it's syntactic sugar which can do really rather a lot to transform your code.
There are lots of videos and blog posts around async, and I would expect that just watching/reading a few of them would give you enough insight to appreciate that this is far from a minor tweak: it radically changes how practical it is to write large amounts of asynchronous code correctly.
Additionally, being pattern-based, async/await doesn't only work on Task / Task<T>. You can await anything which adheres to the awaitable pattern. In practice very few developers will need to implement the pattern themselves, but it allows for methods like Task.Yield which returns a YieldAwaitable rather than a task.

Categories

Resources