Should normal methods inside of an async function be also async? - c#

I have an api end point that is async and then I'm awaiting fetch from database. If I want to use a helper method after the fetching is done of type like calculate something, does it have to be async aswell(it does not call any database, beside using the data that was fetched and makes some calculations)
If it has to be async, how do I do force things to be async then?
Like this?
await Task.Run(() => {
Calculate();
});
Or do I just leave it sync instead.
var numbers = await repo.Numbers.ToListAsync();
Calculate(numbers);

Leave it synchronous if it isn't doing file or database I/O, or other potentially blocking operations.
Think about it this way: if what you ask were true, the entire .NET API would be async, there's no difference between your proposed Calculate example and something like Int32.TryParse or any other random API call.

What you're doing in your example is not ideal.
If your underlying call (Calculate in this case) is synchronous, and there are no other asynchronous operation calls within your API, then there is no point in marking your API as "asynchronous", unless you have to satisfy a contract.
On the side note, though, data retrieval is actually an IO operation, and it should be asynchronous. Instead of wrapping that IO logic in a synchronous "Calculate" method, I'd recommend updating it to be async (you can follow a convention and name it CalculateAsync then). That will allow you to eliminate the Task.Run call as it'll be unnecessary.
To generalize this, an API should be async, if it consumes asynchronous logic. Otherwise - it should be synchronous.

Related

How to make an existing code block async in .net?

I have an existing code block with Linq to SQL queries and HTTP requests, that I'd like to make async for the purpose of using less threads.
Will it suffice to put the code block in an async method, like so?
public async Task<Customer> ProcessACustomer()
{
return await GetCustomer();
}
public Task<Customer> GetCustomer()
{
// Linq to SQL query here
// HTTP request here
Customer customer;
return Task.FromResult<Customer>(customer);
}
...or do I have to make every piece of logic in GetCustomer() async to accomplish this?
My hurdle here is that I have a ton of logic in that method (oversimplified above), so time will be an issue. Also, I can't seem to convert my Linq To SQL queries to async, as the async extension methods are not available for some reason (System.Data.Linq.Table does not contain a definition for FirstOrDefaultAsync() f.ex.).
Will it suffice to put the code block in an async method, like so?
No. The GetCustomer method is not asynchronous. It synchronously performs its work and then returns a completed task. This will not save any threads.
do I have to make every piece of logic in GetCustomer() async to accomplish this?
If you want to convert to async, then you should start at the opposite end. Don't start with the goal of making ProcessACustomer (or GetCustomer) asynchronous. Instead, start with the lowest-level API. Whatever your db access method is, make that asynchronous first and then let the async grow out from there.
My hurdle here is that I have a ton of logic in that method (oversimplified above), so time will be an issue.
This is a classic tradeoff. It may be worthwhile to convert to async, or it may be worthwhile to buy a few more servers instead.

Keep Task and Task.FromResult if method is synchronous or remove Task-stuff at all?

I have a Web API controller (ASP.NET Core 5). Some of my APIs are asynchronous and some of them not. My question is next: Is there any advantages of using public **Task<T>** WebApiMethod + Task.FromResult() in Web API controllers if my method is synchronous?
For example:
public Task<string> GetSomeData()
{
// some synchronous processing...
return Task.FromResult(result);
}
Should I turn the example code above to something like this?
public string GetSomeData()
{
// some synchronous processing...
return result;
}
If the api is doing synchronous work it should have a synchronous signature. it will make the readability and understanding of the function clearer to other developers and will prevent misunderstanding when reading this function again in the future.
In the future, if the method will need to be modified to have an asynchronous task to do, you can change the signature to have an asynchronous signature.
You should use synchronous methods if the work is synchronous.
Yet, you should use Task signatures if you use some form of caching (e.g. with the proxy pattern). Then, of course if you already did the expensive I/O work, use Task.FromResult to return the cached result, and return the I/O task if it has to be newly downloaded.
It shouldn't have much difference in the way it is executed. If you can make the processing part asynchronous then it would make some difference.

C# async tasks: do all participating methods have to be async as well?

When we are dealing with async tasks, the task consists of multiple method calls (possibly of other classes) which in turn consist of yet further method calls. We could call this a tree. Do all methods have to be of type async task for the original task to truly behave async?
Would the answer be true for any kind of background task of other similar languages, mostly Java as well?
(In C#, once I had one of my methods somewhere in this tree get into an infinite loop (talk about a long running task!), yet sadly, the original async task's isRunning property returned false.)
Do all methods have to be of type async task for the original task to truly behave async?
In order to behave asynchronously, an async method must have an await statement for an operation that is not already completed.
I think my async intro blog post would be helpful for you.
Would the answer be true for any kind of background task of other similar languages, mostly Java as well?
Yes.
sadly, the original async task's isRunning property returned false
I assume you mean that the TaskStatus was not TaskStatus.Running. This is normal and expected, since asynchronous tasks are Promise Tasks, not Delegate Tasks (see my blog for more info).
The short answer is no. Async means that work being done by another process can be handed off to that process and so not block the calling thread. All the better if those processes don’t reside on the same machine, since that work will occupy very little compute or IO at the caller. This is achieved by suspending method execution using the async/await mechanism, which promises to resume on some synchronisation context once completed. So, why the overview?
Because this means that we can and should judiciously choose those operations that should be async, and so apply the await keyword in an async method. Some won’t need it, since they are lightweight and adding async to them may even add compute time to them, due to the creation of the async state machine. So the operations in a method can often be a mixture of asynchronous and synchronous code.
And this in turn means that some methods would use the Task return type with async/await, and some will be regular, synchronous methods.
No, they don't have to. Simple example, in a Forms application this
button.Click += async (_, __) =>
{
await Task.Run(() => MyClass.SomeTimeconsumingMethod());
};
still lets you move the window during the execution of SomeTimeconsumingMethod, whereas this one
button.Click += (_, __) =>
{
MyClass.SomeTimeconsumingMethod();
};
doesn't let you do it.
The only requirement for using the await keyword is that the method you are awaiting returns a Task or Task<T>.
The exact implementation of this method (async or return someTask) has no influence on the correctness of the code, although it may influence the function.
Any normal code can run in an async method alongside your await calls. The only significant restriction is that out and ref are not allowed.
Do all methods have to be of type async task for the original task to truly behave async
It depends on what do you mean by "all" word.
Some APIs must not be asynchronous. Think about List<T>.Add, for example. Do you really want it to be asynchronous?
Some APIs should be asynchronous, but there's no asynchronous counterpart (e.g. SMO, or File static class).
Ideally you should do "async all the way", when talking about IO-bound operations. But IRL you can face with violation of this rule, when some part of your async method chain will execute IO-bound operation synchronously.

C# caching and async requests

In this method:
private async List<stuff> GetData()
{
return await _appCache.GetAsync("SiteStructurePages",
() => _repository.GetSomeStuff());
}
is there any reason to keep it async? My code will execute in async manner just once, and all subsequent requests will use cache. Async spreads up to other parts of my application, that doesn't hit database, because lots of stuff is cached.
Edit:
My application is IIS website application.
is there any reason to keep it async?
That really depends on you. If you actually need to take advantage of asynchronous operations, which is being able to scale, then do keep it. Otherwise, if you don't, use a synchronous API. it's all up to you and what you actually make use of in your code base.
I understand the fact that you're worried about async methods going "all the way" and actually altering your entire code-base to become async. That's why you should do it as long as it's worth it.
Side note - you can slightly modify your code to save yourself the async state-machine generation:
private Task<List<stuff>> GetData()
{
return _appCache.GetAsync("SiteStructurePages",
() => _repository.GetSomeStuff());
}
If you can ensure that the call is quick and that it's not going to block a UI thread, then sure, you don't need Async on this one.
However, if such things are not in your control, then I would leave it asynchronous.

Why use Async/await all the way down

I would like to get some clarification on what is the added benefit of using of Await and Async all the way down.
If my application is calling await Func1() (So no blocking to the UI here). and Func1 is calling await Func2(), but the results from Func2() are important for Func1 to complete it's job, then why would I need to make Func2() awaitable. Func1() execution will take just as long because it's waiting on Func2 to finish. All what the await is doing here is adding the StateMachine overhead.
Am I missing something here?
A better slogan is async all the way up. Because you start with an asynchronous operation and make its caller asynchronous and then the next caller etc.
You should use async-await when you have an inherently asynchronous operation (usually I/O but not necessarily) and you don't want to waste a thread idly waiting for the operation to complete. Choosing an async operation instead of a synchronous one doesn't speed up the operation. It will take the same amount of time (or even more). It just enables that thread to continue executing some other CPU bound work instead of wasting resources.
But to be able to await that operation the method needs to be an async one and the caller needs to await it and so forth and so forth.
So async all the way up enables you to actually make an asynchronous call and release any threads. If it isn't async all the way then some thread is being blocked.
So, this:
async Task FooAsync()
{
await Func1();
// do other stuff
}
async Task Func1()
{
await Func2();
// do other stuff
}
async Task Func2()
{
await tcpClient.SendAsync();
// do other stuff
}
Is better than this:
void Foo()
{
Func1();
// do other stuff
}
void Func1()
{
Func2().Wait(); // Synchronously blocking a thread.
// do other stuff
}
async Task Func2()
{
await tcpClient.SendAsync();
// do other stuff
}
The major benefit is the fact that awaiting an asynchronous method returns the worker thread to the pool to be used in other calls (web requests to your .NET MVC web app, for example). The asynchronous work is done on an IO completion thread. When the awaited method finishes, another worker thread will collect the results and resume execution. This prevents worker thread pool exhaustion and allows your application to handle more load (CPU, memory, and network throughput depending).
As for "await all the way down", that seems like an issue to me. Typically await is associated to an external resource (DB call, HTTP request, etc.) that your application must wait on. If you await code that doesn't have external IO dependencies, you're creating overhead that isn't needed. It's possible to have multiple awaits in an async method chain, but awaiting some code that itself calls await but has no other external IO dependency is not good and will just add callback/compiler overhead.
Usually, the reasoning behind async/await goes the other way around:
For whatever reason, you decide that Func2 would be easier to write using await. So you simplify the method by adding the desired awaits, meaning you also have to change the method signature (it will now include the async keyword and a return type of Task or Task<T>).
Because the return type has changed, you can no longer call Func2 like you used to (var result = Func2();), so you're now required to change the calling method, Func1. The easiest way to adapt Func1 will often be to make it async too, and await Func2().
Then, for the same reason (changed signature), you will need to change all calls to Func1, and so on until you get to some kind of entry point (either a UI event handler, or your Main method, or something else).
So you don't start making the "outermost" method async and follow through to the "inner" (called) methods; you usually make things async while going in the opposite direction (from the "innermost" methods back to the calling ones). This other answer calls this idea "async all the way up".
"This async method lacks 'await' operators and will run synchronously" is what happens if you don't await an async method. To harness the benefits of an async method you must await it, turning the caller into an async method which can be awaited etc etc.
From the flow diagram you see that the async method returns a Task (a promise of work to be completed in the future) and yields control to it's caller. The caller can then get on with work not dependent on this result in the meantime. Clearly this needs to bubble up the call stack to find all of this gainful work that can be done without the result (In a UI app this work would include unblocking the UI, which is why it's async all the way up to the the event handler in the below example).
From my initial misreading. So you've found some async code that you need to call, is it worth the async await pattern spreading up your code:
I've heard a lot that the main problem with async-await is it's a much too easy syntax for what it actually does. Program flow gets complicated. I really like async-await, but unfortunately in most the async code I've seen it isn't worth it and is just needlessly ruining my call-stack.
A good thing to keep in mind is the 50ms rule.
"This is the rule that Microsoft followed with the WinRT APIs; anything taking less than 50ms is considered “fast” and close enough to “immediate” that they do not require an asynchronous API."
This is being used in the context of encouraging async-await. However, I think it equally should be applied to tell developers using async-await for essentially immediate functionality to cut it out.
In a UI based application async await provides a very succinct way to handle asynchronous calls resulting in UI updates. If the 'top level' handler from the UI is awaiting a result then there is potentially no real benefit in the whole chain down doing the same unless it makes sense to do so. A design goal of async await was to make async programming look more synchronous and continuous and not have callbacks scattered around etc - making async coding more assessable. It's not something you need to use everywhere arbitrarily.

Categories