Async-await - Am I over doing it? - c#

Recently I've developed doubts about the way I'm implementing the async-await pattern in my Web API projects. I've read that async-await should be "all the way" and that's what I've done. But it's all starting to seem redundant and I'm not sure that I'm doing this correctly. I've a got a controller that calls a repository and it calls a data access (entity framework 6) class - "async all the way". I've read a lot of conflicting stuff on this and would like to get it cleared-up.
EDIT: The referenced possible duplicate is a good post, but not specific enough for my needs. I included code to illustrate the problem. It seems really difficult to get a decisive answer on this. It would be nice if we could put async-await in one place and let .net handle the rest, but we can't. So, am I over doing it or is it not that simple.
Here's what I've got:
Controller:
public async Task<IHttpActionResult> GetMessages()
{
var result = await _messageRepository.GetMessagesAsync().ConfigureAwait(false);
return Ok(result);
}
Repository:
public async Task<List<string>> GetMessagesAsync()
{
return await _referralMessageData.GetMessagesAsync().ConfigureAwait(false);
}
Data:
public async Task<List<string>> GetMessagesAsync()
{
return await _context.Messages.Select(i => i.Message).ToListAsync().ConfigureAwait(false);
}

It would be nice if we could put async-await in one place and let .net handle the rest, but we can't. So, am I over doing it or is it not that simple.
It would be nice if it was simpler.
The sample repository and data code don't have much real logic in them (and none after the await), so they can be simplified to return the tasks directly, as other commenters have noted.
On a side note, the sample repository suffers from a common repository problem: doing nothing. If the rest of your real-world repository is similar, you might have one level of abstraction too many in your system. Note that Entity Framework is already a generic unit-of-work repository.
But regarding async and await in the general case, the code often has work to do after the await:
public async Task<IHttpActionResult> GetMessages()
{
var result = await _messageRepository.GetMessagesAsync();
return Ok(result);
}
Remember that async and await are just fancy syntax for hooking up callbacks. There isn't an easier way to express this method's logic asynchronously. There have been some experiments around, e.g., inferring await, but they have all been discarded at this point (I have a blog post describing why the async/await keywords have all the "cruft" that they do).
And this cruft is necessary for each method. Each method using async/await is establishing its own callback. If the callback isn't necessary, then the method can just return the task directly, avoiding async/await. Other asynchronous systems (e.g., promises in JavaScript) have the same restriction: they have to be asynchronous all the way.
It's possible - conceptually - to define a system in which any blocking operation would yield the thread automatically. My foremost argument against a system like this is that it would have implicit reentrancy. Particularly when considering third-party library changes, an auto-yielding system would be unmaintainable IMO. It's far better to have the asynchrony of an API explicit in its signature (i.e., if it returns Task, then it's asynchronous).
Now, #usr makes a good point that maybe you don't need asynchrony at all. That's almost certainly true if, e.g., your Entity Framework code is querying a single instance of SQL Server. This is because the primary benefit of async on ASP.NET is scalability, and if you don't need scalability (of the ASP.NET portion), then you don't need asynchrony. See the "not a silver bullet" section in my MSDN article on async ASP.NET.
However, I think there's also an argument to be made for "natural APIs". If an operation is naturally asynchronous (e.g., I/O-based), then its most natural API is an asynchronous API. Conversely, naturally synchronous operations (e.g., CPU-based) are most naturally represented as synchronous APIs. The natural API argument is strongest for libraries - if your repository / data access layer was its own dll intended to be reused in other (possibly desktop or mobile) applications, then it should definitely be an asynchronous API. But if (as is more likely the case) it is specific to this ASP.NET application which does not need to scale, then there's no specific need to make the API either asynchronous or synchronous.
But there's a good two-pronged counter-argument regarding developer experience. Many developers don't know their way around async at all; would a code maintainer be likely to mess it up? The other prong of that argument is that the libraries and tooling around async are still coming up to speed. Most notable is the lack of a causality stack when there are exceptions to trace down (on a side note, I wrote a library that helps with this). Furthermore, parts of ASP.NET are not async-compatible - most notably, MVC filters and child actions (they are fixing both of those with ASP.NET vNext). And ASP.NET has different behavior regarding timeouts and thread aborts for asynchronous handlers - adding yet a little more to the async learning curve.
Of course, the counter-counter argument would be that the proper response to behind-the-times developers is to train them, not restrict the technologies available.
In short:
The proper way to do async is "all the way". This is especially true on ASP.NET, and it's not likely to change anytime soon.
Whether async is appropriate, or helpful, is up to you and your application's scenario.

public async Task<List<string>> GetMessagesAsync()
{
return await _referralMessageData.GetMessagesAsync().ConfigureAwait(false);
}
public async Task<List<string>> GetMessagesAsync()
{
return await _context.Messages.Select(i => i.Message).ToListAsync().ConfigureAwait(false);
}
If the only calls you do to asynchronous methods are tail-calls, then you don't really need to await:
public Task<List<string>> GetMessagesAsync()
{
return _referralMessageData.GetMessagesAsync();
}
public Task<List<string>> GetMessagesAsync()
{
return _context.Messages.Select(i => i.Message).ToListAsync();
}
About the only thing you lose is some stack-trace information, but that's rarely all that useful. Remove the await then instead of generating a state-machine that handles the waiting you just pass back the task produced by the called method up to the calling method, and the calling method can await on that.
The methods can also sometimes be inlined now, or perhaps have tail-call optimisation done on them.
I'd even go so far as to turn non-task-based paths into task-based if it was relatively simple to do so:
public async Task<List<string>> GetMeesagesAsync()
{
if(messageCache != null)
return messageCache;
return await _referralMessageData.GetMessagesAsync().ConfigureAwait(false);
}
Becomes:
public Task<List<string>> GetMeesagesAsync()
{
if(messageCache != null)
return Task.FromResult(messageCache);
return _referralMessageData.GetMessagesAsync();
}
However, if at any point you need the results of a task to do further work, then awaiting is the way to go.

Related

Handling synchronous methods in async/await best practices (turtles all the way down)

With async turtles all the way down ...
Some of the background research:
Async/Await - Best Practices in Asynchronous Programming
Async
In code I've seen:
Developers wrap code in a Task.Run() upon entering a method and awaiting it to force it to be async or (or older .NET 4.0 TaskFactory.StartNew())
I've personally just left it synchronous (but it partially violates turtles all the down as different branches often are sync)
I've also seen the attempt to use ValueTask to short-circuit the return as async given the nature of ValueTask with a return value being akin to:
return new ValueTask<int>(valueWantToReturn);
Example psudeo code:
public async Task ParentMethodAsync()
{
// ... do something upon entering
int neededValue = SyncNestedDryMethod(); // ** this part **
await _nthLayer.DoSomethingWithRepoAsync(); // ** same concept applies here
// if there is no asyncronous logic required **
// ... do anything else needed
}
public int SyncNestedDryMethod()
{
// ... do something that requires no real async method signature
// declaration because it is straight synchronous logic (covers reusing
// code for DRY purposes, method-level SRP abstraction (includes moving it
// to an abstracted class -- for future readers), etc.)
// I've seen making the method async then awaiting Task.Run() or
// Task.StartFactory.New() inside this (sync changed to async method)
// to try and force it to be async or last line being:
// return new ValueTask<int>(valueWantToReturn);
// but everything above it being only syncronous logic
}
Is there a best practice to be aware of not found addressed in the respective links (or overlooked) or elsewhere which I have not come across to address abstracting synchronous code into new methods (for DRY purposes, SRP, etc.) that do not have the ability to be async or are forced async all the while following async through and through?
Your question isn't entirely clear, but I think you're asking how to run synchronous code in an asynchronous way? If so, the answer is: you can't.
Using Task.Run() doesn't make the code asynchronous. It just runs the code on a different thread and gives you an asynchronous way to wait for that thread to complete. That may be what you need if you just need to get the work off of the current thread. For example, you would use that in a desktop application where you want to get the work off of the UI thread. But this wouldn't help you at all in ASP.NET.
ValueTask is used for cases where the work might be done asynchronously, but also may complete synchronously too. For example, if data is usually returned from an in memory cache, but refreshing that cache is done asynchronously. This is described in detail here. But if the work is always synchronous, then there is no point using ValueTask, or Task or async.

C# Async when also needing support for synchronous call

I'm in a situation where we have some code that is run by user input (button click), that runs through a series of function calls and result in generating some data (which is a quite heavy operation, several minutes). We'd like to use Async for this so that it doesn't lock up the UI while we're doing this operation.
But at the same time we also have a requirement that the functions will also be available through an API which preferably should be synchronous.
Visualization/Example (pseudo-code):
public async void Button_Click() // from UI context
{
await instanceOfClassA.FuncA();
// some code
}
public async Task ClassA.FuncA()
{
await instanceOfClassB.FuncB()
// some code
}
public async Task ClassB.FuncB()
{
await instanceOfClassC.SomeHeavyFunc()
// some code
}
public async Task ClassC.SomeHeavyFunc()
{
// some heavy calculations
}
// Also need to provide a public synchronous API function
public void SomeClass.SynchronousAPIFunc()
{
// need to call differentInstanceOfClassB.FuncB()
}
Is there a way to make it so that the public API function does the waiting for the async operation internally?
EDIT:
In this post, user Rachel provides two answers to the question. Both seem interesting, though I'm unsure which one would offer the least amount of risk/side effects.
EDIT2:
I should note that we're using .NET v4.6.1.
Thanks in advance.
The problem with making "synchronous" versions of your methods that just call the asynchronous versions is that it can cause deadlocks, especially if the person calling this code is not aware that this is what is happening.
If you really want to make synchronous versions, then follow Microsoft's lead and write completely new methods that do not use any asynchronous code. For example, the implementation for File.ReadAllLines() doesn't use any of the same code as File.ReadAllLinesAsync().
If you don't want to do that, then just don't provide synchronous versions of your methods. Let the caller make the decision on how to deal with it. If they want to block synchronously on it, then they can mitigate the risk of deadlock.
But at the same time we also have a requirement that the functions will also be available through an API which preferably should be synchronous.
If you have the need to expose both a synchronous and asynchronous API, I recommend the boolean argument hack. This looks like:
public Task<T> FuncBAsync() => FuncBAsync(sync: false);
public T FuncB() => FuncBAsync(sync: true).GetAwaiter().GetResult();
public async Task<T> FuncBAsync(bool sync)
{
// Note: is `sync` is `true`, this method ***must*** return a completed task.
...
}
Is there a way to make it so that the public API function does the waiting for the async operation internally?
I do not recommend using direct blocking (e.g., GetAwaiter().GetResult()), as the straightforward implementation will lead to deadlocks.
EDIT: In this post, user Rachel provides two answers to the question.
I strongly recommend against using that solution. It uses a nested message loop with a custom SynchronizationContext, but doesn't do COM pumping. This can cause problems particularly if called from a UI thread. Even if the pumping isn't a problem, this solution can cause unexpected re-entrancy, which is a source of countless, extremely subtle, and difficult-to-find bugs.
You can utilize .GetAwaiter().GetResult()
as per your example, it would look like:
public void SomeClass.SynchronousAPIFunc()
{
// need to call differentInstanceOfClassB.FuncB()
ClassB.FuncB().GetAwaiter().GetResult();
}
Also, a good reference on when to not use the above can be found at Dont Block on Async Code

Implementing Awaitable Async method for NCache Get

We're in the process of refactoring all, or a large portion of our .NET 4.6 MVC WebAPI controller methods to async methods.
This seems like it will work well for methods that have a lower level invocation of a method that is awaitable such as SQL command execution; however we are utilizing an in-memory distributed caching framework by Alachisoft called NCache (4.6 SP2 to be exact), which does not offer any truly asynchronous methods.
Would it be worth creating an async helper method that would expose a awaitable Task<object> return type?
Traditionally using the NCache API, you Get an object from cache by a Key in the following usage;
NCacheObject.Get(string);
The proposal is to create a helper method of the following;
protected static async Task<Object> GetAsync(string key, Cache nCache)
{
Task<Object> getTask = new Task<Object>(() => nCache.Get(key));
getTask.Start();
return await getTask.ConfigureAwait(false);
}
So that it would then allow full waterfall of async methods up to the entry controller method as such;
public static async Task<Tuple<List<SomeModel>, bool, string>> GetSomeModelList(string apiKey)
{
return newTuple<List<SomeModel>, bool, string>(await GetAsync("GetSomeModelKey", CacheInstance).ConfigureAwait(false), true, "Success message");
}
And finally the controller method;
[HttpGet, Route("Route/Method")]
public async Task<ResponseOutputModel<List<SomeModel>>> GetSomeModelList()
{
ResponseOutputModel<List<SomeModel>> resp = new ResponseOutputModel<List<SomeModel>>();
try
{
Tuple<List<SomeModel>, Boolean, String> asyncResp = await CacheProcessing.GetSomeModelList(GetApiKey()).ConfigureAwait(false);
resp.Response = asyncResp.Item1;
resp.Success = asyncResp.Item2;
resp.Message = asyncResp.Item3;
}
catch (Exception ex)
{
LoggingHelper.Write(ex);
resp.StatusCode = Enumerations.ApiResponseStatusCodes.ProcessingError;
resp.Success = false;
resp.Message = ex.Message;
}
return resp;
}
This would complicate the refactoring, as the original methods actually had output parameters for bool success and string message; but it seems this can be accomplished in a decent and quick manner using a Tuple<>; otherwise we could just create a return type model.
To do this properly, there would be many hundreds of methods to refactor; quite an undertaking.
Would this work as expected, and be the best solution to accomplish the objective?
Is it likely worth all of the effort required, with the end goal of increasing scalability and subsequently "performance" of the web servers?
Would it be worth creating an async helper method that would expose a awaitable Task return type?
Nope.
The proposal is to create a helper method of the following
This just queues in-memory work to the thread pool.
(Side note: The task constructor should never be used. Ever. If you need to queue work to the thread pool, use Task.Run instead of the task constructor with Start)
Would this work as expected, and be the best solution to accomplish the objective?
Is it likely worth all of the effort required, with the end goal of increasing scalability and subsequently "performance" of the web servers?
These are the same question. The objective is scalability; asynchrony is just one means to help you accomplish it.
Asynchrony assists scalability on ASP.NET because it frees up a thread that can process other requests. However, if you make methods that are asynchronous by using another thread, then that doesn't assist you at all. I call this "fake asynchrony" - these kinds of methods look asynchronous but they're really just synchronously running on the thread pool.
In contrast to true asynchrony, fake asynchrony will actually hurt your scalability.
As this is a memory cache and Im saying this out of any direct experience with NCache but experiences with other cache systems.
Yes, this would work of course. I'd rather opt for a response struct or a generic class that allows me to define my response type (if it's possible at all). Tuples are not bad, probably would be more performant if you opt for classes instead. But they are not easy on the eyes.
Now, when it comes to performance, there is one question though. Here's a cache server for you and you want fast read-write of course. Accessing a memcache should be easy. As you're directly accessing the memory here, from a performance point of view, it won't really give you much. Are you making sure your code is fully async and you're using the threadpool properly to make things alright? Yes, of course but all it would ever do is add an extra layer or work when you're accessing your cache.
And the moment you're going for async, please do make sure that your memory cache is thread safe. :)

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

Summary: In a library method, when should I use the async and await keywords instead of returning a Task directly?
I believe my question is related to this one. However, that question is about .NET 4.0 and the TPL, while I'm using .NET 4.6 with the async and await keywords. So, I think my question might get different answers because these keywords didn't exist when the linked question was answered.
Explanation: I'm writing a simple wrapper for an external WCF service and the wrapper makes multiple SendAsync calls. Now I think that each wrapper method should just return a Task<> directly without being awaited. My understanding is that async/await should be used on the application layer, and not within a library.
So, for example, here is the approach that I think I should take for each wrapper method:
private Task<SignResponse> GetSignDataAsync(SigningRequestType request)
{
return _service.SendAsync(request);
}
But on the Internet, I found several posts that use this approach instead:
private async Task<SignResponse> GetSignDataAsync(SigningRequestType request)
{
return await _service.SendAsync(request).ConfigureAwait(false);
}
And here is another example that I found on technet:
async Task PutTaskDelay()
{
await Task.Delay(5000);
}
private async void btnTaskDelay_Click(object sender, EventArgs e)
{
await PutTaskDelay();
MessageBox.Show("I am back");
}
So, when should I use the second approach (the one that includes the async and await keywords)? Why not just return a whole Task without making PutTaskDelay async? I think that I should return Task directly whenever it is possible, and use async/await to get a final result in the application layer only. Am I right? If not, what is the difference between the two approaches that I show here?
My concern: When the async and await keywords are used, it seems that it just provides additional work to the compiler without any benefit.
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;
}
Don't take my word for it, because I never understood async/await that well, but what bothered me most about the idea was that all methods using async had to be marked as async as well, which annoyed me to no end.
I guess in a library giving people the option to choose how to use the methods is a good thing, so you should use async, however I always found it more clear to explicitly use the Tasks directly.

Avoid duplicate code with Async

How do you avoid writing the same code twice for an async and a non async method.
I am currently using ASP.NET so I am currently on the request thread, and I quickly learned that he below code (that should show my intent), is definetely the wrong way of doing this.
The application deadlocks, as the await keyword tries to get back on the same thread that the .Result is blocking.
The whole reason I am doing this, is to avoid writing the same "FindAll" code twice.
public IEnumerable<Resource> FindAll()
{
return FindAllAsync().Result;
}
public async Task<IEnumerable<Resource>> FindAllAsync()
{
return await Context.Resources.ToListAsync();
}
So how do you solve this?
How do you avoid writing the same code twice for an async and a non async method.
You can't, in the general case.
The operation in question is either naturally asynchronous or naturally synchronous. In this example (a database request), it is naturally asynchronous. So, make the API asynchronous. That is all.
Stephen Toub has a famous pair of blog posts Should I expose synchronous wrappers for asynchronous methods? and Should I expose asynchronous wrappers for synchronous methods? The short answer to both questions is "no."
You can do various hacks to expose both types of APIs (and Stephen covers each approach in his posts), but the benefits are minuscule compared to the drawbacks.
Synchronous and Asynchronous methods should act differently. Usually that means that synchronous calls should call an API that blocks as a part of the request and async should call the API that is "async all the way"
If you don't want to create a completely synchronous api, in your case, you can use ConfigureAwait(false).
When you mark a Task with ConfigureAwait(false), what you're actually saying is "There's no need to run the continuation (the code after the await) inside the same SynchronizationContext, you may complete inside your current context (Which is usually a ThreadPool thread)"
As for your second method, you can remove the async keyword and save a redundant generation of a state machine:
public IEnumerable<Resource> FindAll()
{
return FindAllAsync().Result;
}
public Task<IEnumerable<Resource>> FindAllAsync()
{
return Context.Resources.ToListAsync();
}
Some reading references:
Stephan Cleary - Dont block on async code
Best practice to call ConfigureAwait(false)
Task.ConfigureAwait(false) MSDN

Categories