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

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.

Related

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

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

Why return await Task.FromResult(true); instead of just return true?

When you create a Xamarin Forms Master-Detail sample with VS2017 you get a MockDataStore class generated with methods such as
public async Task<bool> DeleteItemAsync(string id)
{
var _item = items.Where((Item arg) => arg.Id == id).FirstOrDefault();
items.Remove(_item);
return await Task.FromResult(true);
}
It feels naive to say This is a Microsoft example therefore it must be right.
I don't understand why those methods don't just return true and I've not seen this idiom explained. Is there something subtle I"m missing here, or is this a historic workaround that should have been cleaned up from the templates?
I suppose the reasoning behind this was to prevent "async method lacks await operator" compiler warning. Authors of this autogenerated code wanted to mark function async, because that's what you will do anyway when you implement real functionality. So to prevent compiler warning (no autogenerated code should generate compiler warnings) you need to await something, and there is nothing to await in their code, so they've chosen to await Task.FromResult.
Of course when you write code yourself and not autogenerate it for future edits - you don't need to do this.
TL;DR: When a function returns Task or Task<T> it will be handled asynchronously. But it itself doesn't need to be async.
Using async…await means the compiler builds a state machine to handle this. But if the only thing that you await is the last expression you can avoid this state machine:
public Task<bool> DeleteItemAsync(string id)
{
// Nothing awaitable here...
return Task.FromResult(true);
}
and create a function that runs synchronously – but has the signature and behaviour of an asynchronous function because of the call it makes to something that acts asynchronously.
Why return Task<T>: because that's what the caller is expecting: this cannot be changed without changing all callers, and their callers, and their callers, … all the way down (probably).
So the signature cannot be changed. You have to return something waitable. But you can just return the "waitability" of another result if that's the last thing you do (a bit like achieving tail-recursion).
you get a MockDataStore
So this is only for testing: the overhead is unlikely to be significant and it gives code that can be adapted as a good example of what real code will look like. (Better than much – very poor – scaffolded code which provides a bad example.)
Note: with C#7 this would be a good case to make use of ValueTask<T> to avoid the overhead of allocating a Task<T> when the result is known immediately.
This method might (should) as well be implemented synchronously as it is indeed truly synchronous:
public bool DeleteItem(string id)
{
var _item = items.Where((Item arg) => arg.Id == id).FirstOrDefault();
items.Remove(_item);
return true;
}
It makes no sense for a synchronous method to be named *Async and return a Task<T>.
I guess you are supposed to add your own asynchronous removal logic in there. After all, the generated code is just sample code.
You would then await the actual database operation rather than Task.FromResult(true), i.e. you replace Task.FromResult(true) with an asynchronous call to a method that performs the database query and then returns true once the async method has returned successfully.

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

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.

Why do asynchronous calls in C# need to be declared as such if the method they reside in is declared with the 'async' keyword already?

Now, there's a 99% chance that this "nitpick" I have found is entirely due to my own ignorance - I'm a junior web developer who has only been exposed to C# sporadically for a couple of months, so I apologize in advance for the probable stupidity of my question. Most of my experience is with PHP and JS.
If I have a method declared with the async keyword as such:
public async Task<ActionResult> Create(MyObject myObject)
{
}
Why do I also have to specify that LINQ statements be asynchronous explicitly like so:
public async Task<ActionResult> Create(MyObject myObject)
{
if (ModelState.IsValid)
{
myObject.Id = Guid.NewGuid();
myObject.DisplayId = await db.MyObjects.MaxAsync(m => m.DisplayId) + 1;
db.MyObjects.Add(myObject);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(myObject);
}
Can't the C# compiler be clever enough to figure out that because the method is asynychronous, the LINQ statements I want to execute within the method should be asynchronous too?
I guess my real beef with this is that there's now an asynchronous twin for most LINQ methods (SaveChangesAsync, MaxAsync, FirstOrDefaultAsync), and I have to use the await keyword every time I want to execute such calls. It seems excessively verbose and unnecessary.
If granular control over the synchronicity of the call was still needed, why didn't the C# developers simply allow for an .Await(),.Async(), or Sync() method that I could append?
Can't the C# compiler be clever enough to figure out that because the method is asynychronous, the LINQ statements I want to execute within the method should be asynchronous too?
What if you want to make a synchronous call in an asynchronous method?
Do you want the same method to be synchronous or asynchronous depending on whether or not you're in an asynchronous method? I guess it would be possible for a language to do that, but it would require a fundamentally different model that is not the one used by C#. Also, I'm not sure it would be a good idea; it could be pretty confusing. Better to make things explicit IMO.
I guess my real beef with this is that there's now an asynchronous twin for most LINQ methods (SaveChangesAsync, MaxAsync, FirstOrDefaultAsync), and I have to use the await keyword every time I want to execute such calls. It seems excessively verbose and unnecessary.
Using await or not doesn't have the same meaning. If you don't use await, you just retrieve the task, which can be useful in some scenarios (e.g. if you want to parallelize tasks. For instance, consider the following:
Task t1 = SomeAsyncOperation();
Task t2 = SomeOtherAsyncOperation();
await Task.WhenAll(t1, t2);
In the code above, the operations run in parallel. Now, if you use await on each call:
await SomeAsyncOperation();
await SomeOtherAsyncOperation();
The operations are now sequential.
The developer needs to be in control of this kind of thing. That's why the await cannot be implicit, because it changes the behavior of the code.
If granular control over the synchronicity of the call was still needed, why didn't the C# developers simply allow for an .Await() or .Async() method that I could append?
How would a .Await() method be better than a keyword? Anyway, it wouldn't work. The use of the await keyword transforms the body of the method into a state machine; a method call can't do that.
await completely changes the way code for the method is generated - state machine vs. linear code - so you can't magically implement it with any custom .Await() method because method calls compiled into linear code.
C# generally chooses explicit approach vs. magically guess intentions - so while there are cases when compiler may guess need for await call it does not.
Note that with var it frequently impossible to make a guess either:
var displayId = db.MyObjects.MaxAsync(m => m.DisplayId);
displayId could be Task or if compiler allowed to guess for missing await it could be int.

Categories

Resources