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.
Related
in a dotnet core http application we have a call that performs work, makes several http calls out to backing services, and returns. It was all async await. which meant that the call was waiting for the backing services to perform their work before returning the call to the client. this was causing the call to timeout.
the solution that was presented was to remove the async await all the way down as low as we could then essentially just wrap the http calls (still async task methods) in pragma tags that suppress the warning/compiler error.
This makes me nervous because you don't guarantee that the final (or any) of http requests are made before the calling thread returns and the async machines associated with that thread are cleaned up.
Am I missing something? is this one of those weird but usable situations? or would it be more appropriate to spin off threads to handle those http calls?
You're talking about fire-and-forget, and you're right to be worried. There are several problems with fire-and-forget. This is because "forget" means "forget", and it's almost always the wrong decision to have your application just forget about something.
If there's an exception calling one of those inner HTTP requests, that exception will be ignored, unless you have special logic handling that situation. And remember, there's no outer request anymore, so returning an error isn't possible (there's nowhere for it to return to). So you have the possibility of silently-swallowed errors. This should make you nervous.
Also, you have the problem of not informing ASP.NET that you have ongoing background work. By returning early, you're telling ASP.NET to send the response and that everything is fine, even though in reality, the work isn't done and you have no idea when it will be done or even whether it will succeed. The point here is that nothing upstream of your code (including ASP.NET, IIS/Kestrel, proxies, load balancers) has any idea that your code is still working - after all, your code did just tell all those things that it's done handling that request. Will ASP.NET respond to a shutdown request? Sure! Can IIS do its periodic app pool recycle? Sure! Can your proxy take that node out of rotation when doing a rolling upgrade? Sure! Will your load balancer send it more work since it's not doing anything? Sure! As far as any of those systems know, your app isn't actually handling that request, and that can cause problems, like your "fire and forget" work suddenly disappearing - again, with no exceptions or logs or anything. This should make you nervous.
I'd say the best approach is to fix downstream calls, if possible. Also look into asynchronous concurrency, e.g., starting several calls and then await Task.WhenAll. If these approaches aren't sufficient, then I'd recommend a proper distributed architecture: have the API write to a persistent queue, and have the background work done by a separate application that processes that queue.
I'm not sure if this is technically a call for threading, but strangely enough in my many years of coding, I really haven't had to do this.
Scenario:
API Method is called by a user to kickoff the processing of an
order.
The processing method we need to call next can take a really long
time, so start that but we don't need any reply or acknowledgement if it has been completed, error, etc. as our logging process takes care of all that.
However, user just needs to know the process
has started, so send back a positive response, but kick off the
other methods.
I think this is threading, but for the life of me I'm a bit unsure.
Long running task in WebAPI
It seems like this may be an issue running your process in the background after sending a response.
"ASP.NET (and most other servers) work on the assumption that it's safe to tear down your service once all requests have completed."
As for your situation, what I would do is handle things on the front end and using javascript, jquery, etc, create an on-click event for the order button, and allow it to display an order submitted text or something to that effect.
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.
I was trying to find a good explanation for the difference between synchronous communication vs asynchronous communication for web services, all over the internet. but it seems that even the people who is willing to provide an answer to the problem is also confused with it. and one answer is the complete vice versa for another answer.
If anybody can provide a good explanation about the difference of above matter with a clear idea, it would be helpful for everybody who would face the same problem in the future.
Asynchronous service
Say you have a long running web service (say it reads a large file from the file system and does some processing).
If you set this up as a 'synchronous' web service (using the WCF definition of that), then the calling client will have to wait until the processing completes, and typically this will block on one of the asp.net worker threads while processing completes. For a service with high traffic, this can become problematic.
If you set this up as an asynchronous web service, then what you are saying is that your code is going to delegate some of the long running processing to another thread, or use a non-blocking mechanism, and that this will return at some point in the future (if you are using c# 5.0, then you might want to look at examples of the async and await keywords).
For the example, reading a large file could be done using one of the async ReadFile methods.
This will not block one of the asp.net worker threads, allowing potentially greater throughput.
(There is often some confusion when people refer to making multiple simultaneous calls to the same service (often via AJAX from a web page) - while the calls from the page will typically be made using an asynchronous mechanism in javascript, this is not quite the same as what is described above - I like to keep a distinction between multiple parallel calls and asynchronous calls in my head)
Asynchronous calls
It's also worth noting that you can make an asynchronous call to a service even if that service is not set up to be 'asynchronous'. This is how AJAX calls in javascript will work, e.g.
var jqxhr = $.ajax( "AnyService.svc" )
.done(function() { alert("success"); })
.fail(function() { alert("error"); })
.always(function() { alert("complete"); });
alert("Called");
For this example, you would expect to see 'Called' displayed before 'Success', as this will not wait for the service to return prior to proceeding. The service you are calling does not have to be 'asynchronous'.
Edit
As pointed out in the comments, you can also have a client that calls an 'asynchronous' service in a synchronous manner (i.e. the service will not block worker threads for further requests, but the client will block at that side).
First lets clear your doubt about Synchronous and asynchronous
Synchronous communication is direct communication where the communicators are time synchronized. This means that all parties involved in the communication are present at the same time. This includes, but is not limited to, a telephone conversation (not texting), a company board meeting, a chat room event and instant messaging.
Asynchronous communication does not require that all parties involved in the communication to be present at the same time. Some examples are e-mail messages, discussion boards, blogging, and text messaging over cell phones. In distance (specifically online) education asynchronous communication is the major (sometimes the only) method of communication. Usually, we use different discussion boards in each class with each having its own purpose.
e.g.
synchronous
When I call you on the phone, I dial your number and WAIT until you pick up. Then you say something, and in the very same moment I listen to you. When you finished, I send you data (talk to you) and in the same moment you receive them (listen to me). At the end of our communication one of us says "END OF TRANSMISSION" (Good Bye), the other says "Acknoledged" (Good Bye) and then both ring off.
asynchronous
I write you a letter. I put it to the postoffice, and it will be sent to you. I the meantime I do NOT WAIT. I do many different other things. Then you receive the letter. You read it while I still do many different other things. Then you write me an answer and send it to me. In all those things I am not involved. At the next day I get a (synchronous) message (a signal) from the system (postman). It (he) says: "Here is a message for you". Alternatively I could poll my inbox every five minutes to check if a new letter is there. Then I pause my other work, receive your letter and read your answer. Then I do something according to this answer. But this are things you will not notice, because you are not involved in what I do with your asynchronous answer.
courtesy: How does Synchronous and Asynchronous communication work exactly
well you are not very specific with your problem, but this might help:
at the most basic level synchronous communication is when the communication with the server takes place at the same time that other requests for other assets are sent. for example an ajax call will block other assets from downloading if it is synchronous.
asynchronous communication is when the communication is independant of other assets in the web service/page. this sort of communication is used more often.
Synchronous - You are making a call to a friend, He picked up the call and responded to you.
Asynchronous - You have sent a text to your friend on his mobile, But your friend might reply instantly or may reply 10mins after or may be after 2 days. This case you don't expect a instant answer from your friend.
I'm writing an App using WCF where clients subscribe to a server and then updates get pushed back to the clients.
The subscribers subscribe to the server using a DuplexPipeChannel calling a Subscribe() method on the server.
The server maintains a List<> of subscribers and when there is data to push out to the subscribers it calls a PushData() method.
My intention is to iterate through the list of subscribers calling the push method on each of them in turn.
What I want to know is: Is calling the push method on my Subscriber blocking? Will a failure of connectivity or delay in connecting to one of the subscribers cause the rest of the push calls to be delayed (or worse fail)?
I'm sorry if this is an obvious question, but I've been mostly a .Net 2.0 person up until now so I know very little about WCF.
My WCF code is loosly based on this tutorial.
Another Question
Assuming it is synchronous, am I better off spawning a new thread to deal with the client side requests or would I be better off spawning a new thread for each "push serverside?"
WCF calls are synchronous by default, although they can be configured to be asynchronous. See Jarrett's answer below. Take a look here. Every message you send will receive a result back, whether you actually are expecting data or not.
The call will block depending on what your server does. If PushData on the server actually iterates through the subscriber list and sends a message to each, it will. If PushData only inserts the data and another thread handles sending the data to the subscribers, it will only block while your server inserts the data and returns.
Hope this helps.
Edit: Regarding spawning threads client-side vs server-side. Server-side. If a client calls takes a while, that's while, but if it takes a long time because the server is actually sending out calls to other clients in the same call, then something is wrong. I would actually not really spawn a new thread each time. Just create a producer/consumer pattern on your server side so that whenever a data item is queued, the consumer picks it up. Hell, you can even have multiple consumers.
If you right-click on the Service Reference, you have the option to create Async calls. (There's a checkbox on the setup dialog.) I usually create Async methods and then listen for a result. While it is a bit more work, I can write a much more responsive application using async service operations.