Aysnc webapi post return before finishing - c#

I am making a asp.net webapi call that posts some data to the server and will need to be processed. The client does not need to wait for the processing to finish. I would like to return something like this
HttpResponseMessage objReturn = Request.CreateResponse(HttpStatusCode.Ok);
//start a thread to do some work processing the data
//return while the data is being processed
return objReturn;
Most of the example I find are about how to use async methods and wait for the processing to complete. I need the opposite.
thanks for you suggestions.
more code for those asking, the following code gives me a warning that the method lacks await and will run synchronously.
public async Task<HttpResponseMessage> Post()
{
HttpResponseMessage objReturn = Request.CreateResponse(HttpStatusCode.Ok);
//data processing logic
//something longer running that the client doesnt need to wait for
//like converting a pdf to jpg or other I/O operations
return objReturn;
}

If I read your question correctly, you want a user to call an API, quickly receive a response, and have that trigger a longer running task.
In general, you do not use Web Api to run this longer task, instead yo use a service (i.e. Windows Service).
That service will sit there ... waiting for work ...
your Api will give it work! (Using a database, queues, files, etc.)
However, depending on how important this is, how much effort, and how much time ... you may not want to create a whole separate service. There are some "tools" that can help you.
QueueBackgroundWorkItem
http://hangfire.io/
^^ They will help you run long tasks in your Api directly! ^^

The warning explains most of your problems. Just decorating a method with async does not mean that it runs asynchronous automatically. If you don't have any asynchronous work in your data processing logic it will run synchronously. Event if you have some asynchronous calls in there, the compiler can decide to run it synchronously if it think that's the better option. Remember that asynchronous work does NOT involve another thread.
Some hints what you can do. First, you should make your I/O calls asynchronous. The .NET framework offers a lot you can use here. Second, you should not do that work in a controller. A controller should be small and don't do heavy processing, because it is your communicator to the rest of the world. Pass everything that needs more processing to a queue where a worker role (such as a Windows Service) picks up the work that needs to be done. With that the controller has nothing to do as passing data to the queue, give a result to the client that it was put into the queue ... and done. After that your controller can pick up additional work.

Related

Why should I return Task<IActionResult> in a Controller?

So I have been trying to get the grasp for quite some time now but couldn't see the sense in declaring every controller-endpoint as an async method.
Let's look at a GET-Request to visualize the question.
This is my way to go with simple requests, just do the work and send the response.
[HttpGet]
public IActionResult GetUsers()
{
// Do some work and get a list of all user-objects.
List<User> userList = _dbService.ReadAllUsers();
return Ok(userList);
}
Below is the async Task<IActionResult> option I see very often, it does the same as the method above but the method itself is returning a Task. One could think, that this one is better because you can have multiple requests coming in and they get worked on asynchronously BUT I tested this approach and the approach above with the same results. Both can take multiple requests at once. So why should I choose this signature instead of the one above? I can only see the negative effects of this like transforming the code into a state-machine due to being async.
[HttpGet]
public async Task<IActionResult> GetUsers()
{
// Do some work and get a list of all user-objects.
List<User> userList = _dbService.ReadAllUsers();
return Ok(userList);
}
This approach below is also something I don't get the grasp off. I see a lot of code having exactly this setup. One async method they await and then returning the result. Awaiting like this makes the code sequential again instead of having the benefits of Multitasking/Multithreading. Am I wrong on this one?
[HttpGet]
public async Task<IActionResult> GetUsers()
{
// Do some work and get a list of all user-objects.
List<User> userList = await _dbService.ReadAllUsersAsync();
return Ok(userList);
}
It would be nice if you could enlighten me with facts so I can either continue developing like I do right now or know that I have been doing it wrong due to misunderstanding the concept.
Please read the "Synchronous vs. Asynchronous Request Handling" section of Intro to Async/Await on ASP.NET.
Both can take multiple requests at once.
Yes. This is because ASP.NET is multithreaded. So, in the synchronous case, you just have multiple threads invoking the same action method (on different controller instances).
For non-multithreaded platforms (e.g., Node.js), you have to make the code asynchronous to handle multiple requests in the same process. But on ASP.NET it's optional.
Awaiting like this makes the code sequential again instead of having the benefits of Multitasking/Multithreading.
Yes, it is sequential, but it's not synchronous. It's sequential in the sense that the async method executes one statement at a time, and that request isn't complete until the async method completes. But it's not synchronous - the synchronous code is also sequential, but it blocks a thread until the method completes.
So why should I choose this signature instead of the one above?
If your backend can scale, then the benefit of asynchronous action methods is scalability. Specifically, asynchronous action methods yield their thread while the asynchronous operation is in progress - in this case, GetUsers is not taking up a thread while the database is performing its query.
The benefit can be hard to see in a testing environment, because your server has threads to spare, so there's no observable difference between calling an asynchronous method 10 times (taking up 0 threads) and calling a synchronous method 10 times (taking up 10 threads, with another 54 to spare). You can artificially restrict the number of threads in your ASP.NET server and then do some tests to see the difference.
In a real-world server, you usually want to make it as asynchronous as possible so that your threads are available for handling other requests. Or, as described here:
Bear in mind that asynchronous code does not replace the thread pool. This isn’t thread pool or asynchronous code; it’s thread pool and asynchronous code. Asynchronous code allows your application to make optimum use of the thread pool. It takes the existing thread pool and turns it up to 11.
Bear in mind the "if" above; this particularly applies to existing code. If you have just a single SQL server backend, and if pretty much all your actions query the db, then changing them to be asynchronous may not be useful, since the scalability bottleneck is usually the db server and not the web server. But if your web app could use threads to handle non-db requests, or if your db backend is scalable (NoSQL, SQL Azure, etc), then changing action methods to be asynchronous would likely help.
For new code, I recommend asynchronous methods by default. Asynchronous makes better use of server resources and is more cloud-friendly (i.e., less expensive for pay-as-you-go hosting).
If your DB Service class has an async method for getting the user then you should see benefits. As soon as the request goes out to the DB then it is waiting on a network or disk response back from the service at the other end. While it is doing this the thread can be freed up to do other work, such as servicing other requests. As it stands in the non-async version the thread will just block and wait for a response.
With async controller actions you can also get a CancellationToken which will allow you to quit early if the token is signalled because the client at the other end has terminated the connection (but that may not work with all web servers).
[HttpGet]
public async Task<IActionResult> GetUsers(CancellationToken ct)
{
ct.ThrowIfCancellationRequested();
// Do some work and get a list of all user-objects.
List<User> userList = await _dbService.ReadAllUsersAsync(ct);
return Ok(userList);
}
So, if you have an expensive set of operations and the client disconnects, you can stop processing the request because the client won't ever receive it. This frees up the application's time and resources to deal with requests where the client is interested in a result coming back.
However, if you have a very simple action that requires no async calls then I probably wouldn't worry about it, and leave it as it is.
You are missing something fundamental here.
When you use async Task<> you are effectively saying, "run all the I/O code asynchronously and free up processing threads to... process".
At scale, your app will be able to serve more requests/second because your I/O is not tying up your CPU intensive work and vice versa.
You're not seeing much benefit now, because you're probably testing locally with plenty of resources at hand.
See
Understanding CPU and I/O bound for asynchronous operations
Async in depth
As you know, ASP.NET is based on a multi-threaded model of request execution. To put it simply, each request is run in its own thread, contrary to other single thread execution approaches like the event-loop in nodejs.
Now, threads are a finite resource. If you exhaust your thread pool (available threads) you can't continue handling tasks efficiently (or in most cases at all). If you use synchronous execution for your action handlers, you occupy those threads from the pool (even if they don't need to be). It is important to understand that those threads handle requests, they don't do input/output. I/O is handled by separate processes which are independent of the ASP.NET request threads. So, if in your action you have a DB fetch operation that takes let's say 15 seconds to execute, you're forcing your current thread to wait idle 15 seconds for the DB result to be returned so it can continue executing code. Therefore, if you have 50 such requests, you'll have 50 threads occupied in basically sleep mode. Obviously, this is not very scalable and becomes a problem soon enough. In order to use your resources efficiently, it is a good idea to preserve the state of the executing request when an I/O operation is reached and free the thread to handle another request in the meantime. When the I/O operation completes, the state is reassembled and given to a free thread in the pool to resume the handling. That's why you use async handling. It lets you use your finite resources more efficiently and prevents such thread starvation. Of course, it is not an ultimate solution. It helps you scale your application for higher load. If you don't have the need for it, don't use it as it just adds overhead.
The result returns a task from an asynchronous (non-blocking) operation which represents some work that should be done. The task can tell you if the work is completed and if the operation returns a result, the task gives you the result which won't be available until the task is completed. You can learn more about C# asynchronous programming from the official Microsoft Docs:
https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task?view=net-5.0
Async operations return a Task(it is not the result, but a promise made that will have the results once the task is completed.
The async methods should be awaited so that it waits till the task is completed. if you await an async method, the return values won't be a task anymore and will be the results you expected.
Imagine this async method:
async Task<SomeResult> SomeMethod()
{
...
}
the following code:
var result = SomeMethod(); // the result is a Task<SomeResult> which may have not completed yet
var result = await SomeMethod(); // the result is type of SomeResult
Now, why do we use async methods instead of sync methods:
Imagine that a Method is doing some job that may take a long time to complete, when it is done sync all other requests will be waiting till the execution of this long taking job to complete, as they are all happening in the same thread. However when it is async, the task will be done in a (possibly another) thread and will not block the other requests.

How to wait on an async method in third party library - web api

I am using SendGrid (cloud based SMTP service) to send emails from a web api project. I want my application to wait/block (for say 30 secs) until I have a response from SendGrid before returning the response to the client, rather than returning immediately. The SendGrid library has a DeliverAsync method which returns a Task.
I have been looking at how I might Wait on the task.
I have read endless articles about how one might do this and understand that if it was my own code I would use the ConfigureAwait(false) on the task to prevent a deadlock and allow me to Wait. The problem here is that the code is not mine! It doesn't look like SendGrid have a synchronous Send method.
I do not have async controllers wired up, although appreciate this would be a way to do this, but I'd like to know if there is another way I could do this.
Hope this makes sense!!
If you can await all the way up to and including the controller action, you should, and as that's your code it should be achievable. In that case, at most you might want to consider ConfigureAwait(true) for the call from the controller method only, and have the rest (downwards) as ConfigureAwait(false) (as library methods should be). Most of the time you don't even need the context preserved in the controller action - it depends what you do there - and in that case use ConfigureAwait(false) there too.
You use "wait/block" as though they're the same, but in the TAP world they're quite different. Using await will wait for the SendGrid() call to complete before continuing, while not blocking the calling thread.
If you can't do that, it's far less-preferable to use the blocking .Wait() or .Result, or as others mention GetAwaiter().GetResult(). All 3 will block the caller as well. In Web API you can often get away with this; but in other contexts - e.g. WinForms - you probably won't.
As it's your code, use await.

How do asynchronous GET requests work?

I THINK I understand the basic principle of an asynchronous POST method from a high level view point. The big advantage is that the caller gets a quick response, even though the processing of the data from the POST might not be completed yet.
But I don't really understand how this applies to a GET method. The response needs to contain the data, so how can there BE a response before processing is completed? Why have an API with a GET request handler that utilizes asynchronous methods?
I don't think it matters for this general type of question, but I'm writing in C# using Web API.
On the network there is no such thing as an async HTTP call. It's just data flowing over TCP. The server can't tell whether the client is internally sync or async.
the caller gets a quick response
Indeed, the server can send the response line and headers early and data late. But that has nothing to do with async IO or an async .NET server implementation. It's just some bytes arriving early and some late.
So there is no difference between GET and POST here.
why ... utilize asynchronous methods?
They can have scalability benefits for the client and/or the server. There is no difference at the HTTP level.
So the app can do other things that don't need the data.
If you implement a GET as synchronous (and let's say you are on a bad network, where it takes 20 seconds to get it), you can't
Show progress
Allow the user to cancel
Let them initiate other GETs
Let them use other parts of the app
EDIT (see comments): The server wants to respond asynchronously for mostly the same reason (to give up the thread). Actually getting the data might be asynchronous and take some time -- you wouldn't want to block the thread for the whole time.
It doesn't make any sense if you're building a RESTful API, in which GET should return a resource (or a collection) and be idempotent (not make any changes).
But if you're not following those principles, a GET request could perform some work asynchronously. For example, GET /messages/3 could return the message to the client, but then asynchronously do other work like:
mark the message as read
send a push notification to the user's other clients indicating that the message is read
schedule a cronjob 30 days in the future to delete the message
etc.
None of these would be considered a RESTful API, but are still used from time to time.

Is it advisable to create thread for each client request?

Code:
class Controller
{
Some Action Method()
{
...
...
new Thread(() =>
{
//WCF cal- wil execute for around 10 secs.
var result = service.SubmitAndCreateApp(params);
sessionModel.IsAppCreated = result;
}).Start();
return jsonresult;
}
}
Since my WCF call is taking too much time, I don't want to use thread pool and make it starve.
It is evident here that the thread is being created for each client request. How can I optimize this or any other alternative way to achieve this in .Net 4.0 (VS 2010)?
To put it simply: no, don't do this.
That said, you can look at the Task Parallel Library (TPL) in ASP.Net, which can achieve exactly what you are trying to do.
Quick search yielded this posting, which I only glanced over but seems on-point:
http://vizagtechie.blogspot.com/2013/03/parallel-programming-in-aspnet-mvc.html
No. Your server will get DDOS'ed completely. At the very least, request a thread from the thread pool rather than creating your own by hand. If the thread pool runs out, you'll be waiting for one to become available. The rest of the server will continue to be able to work. Of course, your mileage may vary based on many factors.
Each request already gets a thread, so by adding another thread manually, you're creating two threads per request, effectively having your server's ability to field requests. Now, I won't be as apocalyptic as others: on a beefy enough server not fielding thousands of requests per second or more, you'll probably still be okay. It's still bad design, though.
You didn't mention what version of C# you're using on but on 5.0+, you now have async which is how you'd typically handle this situation:
public async Task<ActionResult> SomeActionWithLongRunningProcess()
{
await LongRunningProcess();
return View();
}
This will cause .NET to offload the request, freeing up the thread, until LongRunningProcess() completes.
Your code can complete the call to Some Action Method() and return jsonresult prior to the completion of your WCF call to service.SubmitAndCreateApp(params) (for practical purposes, assume this will happen 100% of the time). If you want that to happen, then your code is fine. If you need the response from the service call in sessionModel.IsAppCreated for your JSON result, however, your code is very broken.
To fix this, you would need to block the action method's thread until the thread it created terminates. This fact along with the fact that the underlying WCF communication channel will already create its own thread to await response from the WCF service call (a synchronous WCF call is really just an async call that blocks until the response is received) makes creating a new thread pointless.

Why Wait for Asynchronous Web Services Calls

I was going through MSDN documentation on WebServices. Here and here, both these links talk about calling a webservice and wait for the response, which is also a general trend that I have seen while asynch implementation.
I don't understand "why do we need to wait for service call to return"? And, if we are waiting why don't make an synchronous call. What is the difference between an "asynch call followed by wait" and a "synchronous call"?
To be useful, the asynchronous call needs to do its thing while you go do something else. There are two ways to do that:
Provide a callback method for the asynchronous handle, so that it can notify you when it is completed, or
Periodically check the asynchronous handle to see if its status has changed to "completed."
You wouldn't use a WaitHandle to do these two things. However, the WaitHandle class makes it possible for clients to make an asynchronous call and wait for:
a single XML Web service
(WaitHandle.WaitOne),
the first of many XML Web services
(WaitHandle.WaitAny), or
all of many XML Web services
(WaitHandle.WaitAll)
to return results.
In other words, if you use WaitOne or WaitAny on an asynchronous web service that returns several results, you can obtain a single result from your web service call, and process it while you are waiting on the remaining results.
One very practical use of asynchronous calls is stuff like this
http://i.msdn.microsoft.com/Bb760816.PB_oldStyle%28en-us,VS.85%29.png
If you want to update your UI while you're waiting for a 'server' to do something, you need to make an asynchronous call. If you make a synchronous call, your code will be stuck waiting, but if you make an asynchronous call you can update the UI or even let the user go do other stuff while you're waiting for the callback. This goes beyond UI, you may make an asynchronous call to start some non-critical task and continue on with your code and its possible you don't even register for a callback if the result is unimportant.
If you do NOTHING while waiting for the asyncronous call, then its less useful.
Using asynchronous call can free up your application to do other things while waiting for the response. Since there is a fairly large amount of time (in computer cycles) waiting for a web server to respond, that time can be used for better things such as displaying a status update or doing some other work.
For example, if you had a program that performed a complicated calculation and a step of that calculation included using some reference data from a remote web service. By calling the web service asynchronously at the start of the calculation, continuing the parts of computation that can be performed locally, and then using the result of the web service call when it is available to complete the computation you can reduce the overall time of the calculation.
Since your application code is not blocked waiting for the web service to respond, you are able to utilize that wait time to the benefit of the user.
Another reason is scaling, particularly in web sites that make calls to other web services. By using asynchronous page methods (or tasks), IIS can scale your application more effectively by deferring your pages that are waiting on asynchronous web requests to whats known as an "IO thread", freeing up the main ASP.NET worker threads to serve more web pages.
The first example you're linking to issues an async call and then immediately waits for the result. Other than forking off the job to another thread, there's little difference between this and a synchronous call as far as I can tell.
The other example, however, talks about doing multiple async calls at once. If this is the case, it makes sense to launch all calls and then wait because the calls may execute in parallel.
One of the possible uses of an asynchronous call followed by a wait is that asynchronous operations often support cancellation whereas blocking calls do not. Combined with the CancellationToken pattern in .NET 4.0 (or a similar custom pattern pre-.NET4) you can create an operation that appears to be synchronous but can be cancelled easily.

Categories

Resources