Make all conroller methods async easy way - c#

I have a web api with controller methods being like this:
public HttpResponseMessage DoSmth() {
doingSmth();
}
I've read about how server threads here: Why should I return Task<IActionResult> in a Controller?
and here: https://learn.microsoft.com/en-us/archive/msdn-magazine/2014/october/async-programming-introduction-to-async-await-on-asp-net#synchronous-vs-asynchronous-request-handling
The implementation of business\data access layers is syncronous (and huge) and there is no time left to refactor everything into async task<>.
Is there some way to refactor only the controller, i.e. "topmost" methods into being asyncronous so server won't run out of threads?

Is there some way to refactor only the controller, i.e. "topmost" methods into being asyncronous so server won't run out of threads?
No.
You can think of it this way: synchronous calls block a thread. As long as your business logic / DAL methods are synchronous, they will block a thread.
As some have noted in the comments, Task.Run will allow those methods to block a thread pool thread instead of the calling thread, and that's a fine approach for many GUI apps (block thread pool threads instead of the GUI thread), but it's counterproductive on server apps (block one thread pool thread instead of another thread pool thread).
I recommend first analyzing your app and determining which requests are the slowest or most frequently called, and changing just those to be async all the way. You can use the flag argument hack (attribution: me) to avoid code duplication in your logic/DAL types when creating asynchronous equivalents of synchronous methods.

Related

Do I always need to use async/await?

I wanted to ask you about async/await. Namely, why does it always need to be used? (all my friends say so)
Example 1.
public async Task Boo()
{
await WriteInfoIntoFile("file.txt");
some other logic...
}
I have a Boo method, inside which I write something to files and then execute some logic. Asynchrony is used here so that the stream does not stop while the information is being written to the file. Everything is logical.
Example 2.
public async Task Bar()
{
var n = await GetNAsync(nId);
_uow.NRepository.Remove(n);
await _uow.CompleteAsync();
}
But for the second example, I have a question. Why here asynchronously get the entity, if without its presence it will still be impossible to work further?
why does it always need to be used?
It shouldn't always be used. Ideally (and especially for new code), it should be used for most I/O-based operations.
Why here asynchronously get the entity, if without its presence it will still be impossible to work further?
Asynchronous code is all about freeing up the calling thread. This brings two kinds of benefits, depending on where the code is running.
If the calling thread is a UI thread inside a GUI application, then asynchrony frees up the UI thread to handle user input. In other words, the application is more responsive.
If the calling thread is a server-side thread, e.g., an ASP.NET request thread, then asynchrony frees up that thread to handle other user requests. In other words, the server is able to scale further.
Depending on the context, you might or might not get some benefit. In case you call the second function from a desktop application, it allows the UI to stay responsive while the async code is being executed.
Why here asynchronously get the entity, if without its presence it will still be impossible to work further?
You are correct in the sense that this stream of work cannot proceed, but using async versions allows freeing up the thread to do other work:
I like this paragraph from Using Asynchronous Methods in ASP.NET MVC 4 to explain the benefits:
Processing Asynchronous Requests
In a web app that sees a large number of concurrent requests at start-up or has a bursty load (where concurrency increases suddenly), making web service calls asynchronous increases the responsiveness of the app. An asynchronous request takes the same amount of time to process as a synchronous request. If a request makes a web service call that requires two seconds to complete, the request takes two seconds whether it's performed synchronously or asynchronously. However during an asynchronous call, a thread isn't blocked from responding to other requests while it waits for the first request to complete. Therefore, asynchronous requests prevent request queuing and thread pool growth when there are many concurrent requests that invoke long-running operations.
Not sure what you mean by
without its presence it will still be impossible to work further
regarding example 2. As far as I can tell this code gets an entity by id from its repository asynchronously, removes it, then completes the transaction on its Unit of Work. Do you mean why it does not simply remove the entry by id? That would certainly be an improvement, but would still leave you with an asynchronous method as CompleteAsync is obviously asynchronous?
As to your general question, I don't think there is a general concensus to always use async/await.
In your second example there with the async/await keywords you are getting the value of the n variable asynchronously. This might be necessary because the GetNAsync method is likely performing some time-consuming operation, such as querying a database or perhaps you might be calling a webservice downstream, that could block the main thread of execution. By calling the method asynchronously, the rest of the code in the Bar method can continue to run while the query is being performed in the background.
But if in the GetNAsync you are just calling another method locally that is doing some basic CPU bound task then the async is pointless in my view. Aync works well when you are sure you need to wait such as network calls or I/O bound calls that will definitely add latency to your stack.

SynchronizationContext used in asynchronous server methods

So I have an async grpc C# server that needs to do a lot of cross talk between server methods (eg, a streaming response value for a stream rpc could be generated from another rpc).
I have tried setting the SynchronizationContext to a single thread based context, but server methods still seem to be called from arbitrary threads.
How could I ensure that all server methods are called on the same thread, with async/await continuations also on the same thread?
For example, see the following RPC handler:
public override Task<ResponseProto> TestRpc(RequestProto request, ServerCallContext context)
{
// Call shared instance method - could be called from
// multiple concurrent grpc requests, or streamed responses etc
SharedInstanceMethod();
// This is different every call... making a cross-thread issue
// when calling SharedInstanceMethod();
int threadId = Thread.CurrentThread.ManagedThreadId;
}
Note that in this example, SharedInstanceMethod() is a placeholder for a lot of other functions and other asynchronous events - I'm not looking to make SharedInstance thread safe.
To get continuations to run on the same thread, you could use JoinableTaskFactory.Run(() => ...) from vs-threading, which sets a SynchronizationContext to achieve this.
A problem with this is that as soon as you hit a .ConfigureAwait(false) you will lose this context, and continuations will end up running back on the thread pool threads, so if you are calling 3rd party libraries then you cannot guarantee this behavior, and if they are following best practice, then they will likely be using .ConfigureAwait(false).
But going back to your question, I don't think this is what you want. It sounds like you don't have an asynchronous workflow that needs to be forced to run synchronously on 1 thread (which is good, cause it's not ideal). You have a method that cannot be called concurrently and needs some synchronization around it, you should use lock and add a private static object field to lock on.

C# async/await - UI thread vs. other threads [duplicate]

I've been reading about the new async and await operators in C# and tried to figure out in which circumstances they would possibly be useful to me. I studied several MSDN articles and here's what I read between the lines:
You can use async for Windows Forms and WPF event handlers, so they can perform lengthy tasks without blocking the UI thread while the bulk of the operation is being executed.
async void button1_Click(object sender, EventArgs e)
{
// even though this call takes a while, the UI thread will not block
// while it is executing, therefore allowing further event handlers to
// be invoked.
await SomeLengthyOperationAsync();
}
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
In other words, if you create a thread with an ordinary good old ThreadStart entry point (or a Console application with good old static int Main(string[] args)), then you cannot use async and await because at one point you would have to use await, and make the method that uses it async, and hence in the calling method you also have to use await and make that one async and so on. But once you reach the thread entry point (or Main()), there's no caller to which an await would yield control to.
So basically you cannot use async and await without having a GUI that uses the standard WinForms and WPF message loop. I guess all that makes indeed sense, since MSDN states that async programming does not mean multithreading, but using the UI thread's spare time instead; when using a console application or a thread with a user defined entry point, multithreading would be necessary to perform asynchronous operations (if not using a compatible message loop).
My question is, are these assumptions accurate?
So basically you cannot use async and await without having a GUI that uses the standard WinForms and WPF message loop.
That's absolutely not the case.
In Windows Forms and WPF, async/await has the handy property of coming back to the UI thread when the asynchronous operation you were awaiting has completed, but that doesn't mean that's the only purpose to it.
If an asynchronous method executes on a thread-pool thread - e.g. in a web service - then the continuation (the rest of the asynchronous method) will simply execute in any thread-pool thread, with the context (security etc) preserved appropriately. This is still really useful for keeping the number of threads down.
For example, suppose you have a high traffic web service which mostly proxies requests to other web services. It spends most of its time waiting for other things, whether that's due to network traffic or genuine time at another service (e.g. a datbase). You shouldn't need lots of threads for that - but with blocking calls, you naturally end up with a thread per request. With async/await, you'd end up with very few threads, because very few requests would actually need any work performed for them at any one point in time, even if there were a lot of requests "in flight".
The trouble is that async/await is most easily demonstrated with UI code, because everyone knows the pain of either using background threads properly or doing too much work in the UI thread. That doesn't mean it's the only place the feature is useful though - far from it.
Various server-side technologies (MVC and WCF for example) already have support for asynchronous methods, and I'd expect others to follow suit.
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
Not true - methods marked async just mean they can use await, but callers of those methods have no restrictions. If the method returns Task or Task<T> then they can use ContinueWith or anything else you could do with tasks in 4.0
A good non-UI example is MVC4 AsyncController.
Ultimately, async/await is mostly about getting the compiler rewriting so you can write what looks like synchronous code and avoid all the callbacks like you had to do before async/await was added. It also helps with the SynchronizationContext handling, useful for scenarios with thread affinity (UI frameworks, ASP.NET), but even without those, it's still useful. Main can always do DoStuffAsync().Wait(); for instance. :)
My question is, are these assumptions accurate?
No.
You can use async for Windows Forms and WPF event handlers, so they can perform lengthy tasks without blocking the UI thread while the bulk of the operation is being executed.
True. Also true for other UI applications including Silverlight and Windows Store.
And also true for ASP.NET. In this case, it's the HTTP request thread that is not blocked.
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
This is a best practice ("async all the way down"), but it's not strictly required. You can block on the result of an asynchronous operation; many people choose to do this in Console applications.
an ordinary good old ThreadStart entry point
Well... I do have to take issue with "ordinary good old". As I explain on my blog, Thread is pretty much the worst option you have for doing background operations.
I recommend you review my introduction to async and await, and follow up with the async / await FAQ.
async-await is only wrapper for Task class manipulations, which is part of so named Tasks Parallel Library - TPL(published before async-await auto code generation tech.)
So fact is you may not use any references to UI controls within async - await.
Typically async-await is powerfull tool for any web and server relations, loading resources, sql. It works with smart waiting data with alive UI.
Typically TPL application: from simple big size loop till multi stages parallel calculations in complex calculations based on shared data (ContinueWith and so on)

Use of async/await in console or web apps

As I understand it, the async/await feature in C# splits up the segments between await calls into callback methods that run on the calling thread after each awaited method has returned on a separate worker thread. The calling thread is "free" during the waiting time. The callback must be scheduled on the calling thread through some sort of event loop.
This event loop only exists in GUI applications like Windows Forms or WPF. Freeing this loop makes sure the UI remains responsive for other user interaction during long operations.
Console apps and web apps (ASP.NET) do not have such event loops, so this callback mechanism doesn't work. But then again, they do not have an event loop because they don't need one. There is no user trying to interact with the running program at any time, expecting immediate feedback. So there's no need to free the calling thread for that. It doesn't matter how many threads the operation uses, it only returns after the last bit is done.
So what's the use of async and await in console and web apps, or any kind of non-interactive code in general, like for example Windows services? How is that different or more efficient compared to simple synchronous calls?
I'm designing an API that is used by GUI and non-interactive (service and web) programs and have a hard time understanding how it behaves in non-GUI environments.
The point with async-await is that the calling thread is always freed up when you reach the first asynchronous point (i.e. the first await of an uncompleted task).
In UI apps you have a SynchronizationContext that posts the code after the awaits to the UI thread because code that interacts with the UI must be executed by the UI thread otherwise you'll get an exception. You can control that by using ConfigureAwait(false).
In console apps (and services, etc.) there's no such need, so that code runs on some ThreadPool thread. The calling thread (which is likely to be also a ThreadPool thread) was freed up and was able to do other kinds of work in the meantime instead of blocking synchronously. So async-await improves scalability as it enables doing more work with the same amount of threads.
i3arnon's answer is (as usual) excellent.
So what's the use of async and await in console and web apps, or any kind of non-interactive code in general, like for example Windows services?
The primary benefit of async on the client side is responsiveness; the primary benefit of async on the server side is scalability.
How is that different or more efficient compared to simple synchronous calls?
Client-side responsiveness and server-side scalability are achieved by the same mechanism: freeing up the calling thread. Thus, async is all about using fewer threads. On the server side, using fewer threads allows your app to make maximum use of the existing threadpool.
As I understand it, the async/await feature in C# splits up the segments between await calls into callback methods that run on the calling thread after each awaited method has returned on a separate worker thread.
This is why I'm answering. I just can't let this one go. Every time "thread" is mentioned in this understanding, it's wrong. This part is correct: await does "split up" an async method into segments.
1) The callback methods are not run on the calling thread. Rather, await will capture a "context" and resume the method on that context. On ASP.NET apps and Console apps in particular, the context does not imply a particular thread. I explain how await captures context in detail on my async intro blog post.
2) Async APIs are not normally executed on worker threads. The entire point of async is to free up threads, so blocking thread pool threads wouldn't make sense. I explain how asynchronous I/O is almost threadless in my blog post on There Is No Thread.
Async / await has nothing to do with multi threading, to quote MSDN:
The async and await keywords don't cause additional threads to be
created. Async methods don't require multithreading because an async
method doesn't run on its own thread.
Async / await allows you to structure your code with regards to long running operations (could be CPU work or I/O work). So this is applicable to any type of program (GUI, Web Service, console etc)

Is async and await exclusively for GUI-based asynchronous programming?

I've been reading about the new async and await operators in C# and tried to figure out in which circumstances they would possibly be useful to me. I studied several MSDN articles and here's what I read between the lines:
You can use async for Windows Forms and WPF event handlers, so they can perform lengthy tasks without blocking the UI thread while the bulk of the operation is being executed.
async void button1_Click(object sender, EventArgs e)
{
// even though this call takes a while, the UI thread will not block
// while it is executing, therefore allowing further event handlers to
// be invoked.
await SomeLengthyOperationAsync();
}
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
In other words, if you create a thread with an ordinary good old ThreadStart entry point (or a Console application with good old static int Main(string[] args)), then you cannot use async and await because at one point you would have to use await, and make the method that uses it async, and hence in the calling method you also have to use await and make that one async and so on. But once you reach the thread entry point (or Main()), there's no caller to which an await would yield control to.
So basically you cannot use async and await without having a GUI that uses the standard WinForms and WPF message loop. I guess all that makes indeed sense, since MSDN states that async programming does not mean multithreading, but using the UI thread's spare time instead; when using a console application or a thread with a user defined entry point, multithreading would be necessary to perform asynchronous operations (if not using a compatible message loop).
My question is, are these assumptions accurate?
So basically you cannot use async and await without having a GUI that uses the standard WinForms and WPF message loop.
That's absolutely not the case.
In Windows Forms and WPF, async/await has the handy property of coming back to the UI thread when the asynchronous operation you were awaiting has completed, but that doesn't mean that's the only purpose to it.
If an asynchronous method executes on a thread-pool thread - e.g. in a web service - then the continuation (the rest of the asynchronous method) will simply execute in any thread-pool thread, with the context (security etc) preserved appropriately. This is still really useful for keeping the number of threads down.
For example, suppose you have a high traffic web service which mostly proxies requests to other web services. It spends most of its time waiting for other things, whether that's due to network traffic or genuine time at another service (e.g. a datbase). You shouldn't need lots of threads for that - but with blocking calls, you naturally end up with a thread per request. With async/await, you'd end up with very few threads, because very few requests would actually need any work performed for them at any one point in time, even if there were a lot of requests "in flight".
The trouble is that async/await is most easily demonstrated with UI code, because everyone knows the pain of either using background threads properly or doing too much work in the UI thread. That doesn't mean it's the only place the feature is useful though - far from it.
Various server-side technologies (MVC and WCF for example) already have support for asynchronous methods, and I'd expect others to follow suit.
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
Not true - methods marked async just mean they can use await, but callers of those methods have no restrictions. If the method returns Task or Task<T> then they can use ContinueWith or anything else you could do with tasks in 4.0
A good non-UI example is MVC4 AsyncController.
Ultimately, async/await is mostly about getting the compiler rewriting so you can write what looks like synchronous code and avoid all the callbacks like you had to do before async/await was added. It also helps with the SynchronizationContext handling, useful for scenarios with thread affinity (UI frameworks, ASP.NET), but even without those, it's still useful. Main can always do DoStuffAsync().Wait(); for instance. :)
My question is, are these assumptions accurate?
No.
You can use async for Windows Forms and WPF event handlers, so they can perform lengthy tasks without blocking the UI thread while the bulk of the operation is being executed.
True. Also true for other UI applications including Silverlight and Windows Store.
And also true for ASP.NET. In this case, it's the HTTP request thread that is not blocked.
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
This is a best practice ("async all the way down"), but it's not strictly required. You can block on the result of an asynchronous operation; many people choose to do this in Console applications.
an ordinary good old ThreadStart entry point
Well... I do have to take issue with "ordinary good old". As I explain on my blog, Thread is pretty much the worst option you have for doing background operations.
I recommend you review my introduction to async and await, and follow up with the async / await FAQ.
async-await is only wrapper for Task class manipulations, which is part of so named Tasks Parallel Library - TPL(published before async-await auto code generation tech.)
So fact is you may not use any references to UI controls within async - await.
Typically async-await is powerfull tool for any web and server relations, loading resources, sql. It works with smart waiting data with alive UI.
Typically TPL application: from simple big size loop till multi stages parallel calculations in complex calculations based on shared data (ContinueWith and so on)

Categories

Resources