In my scenario when ever user changes some fields in the program and does a SAVE, a webserivce request is sent to save some logging information into the database. I did some search on the website and found this solution for Async calls:
ThreadPool.QueueUserWorkItem(delegate
{
// Create an instance of my webservice object.
// call its Log webmethod.
});
But since I don't have much experience with webservices and Async calls so I wanted to show you the scenario I have and the way I am handling it to get your opinion about it and if it the right way to do this. Thanks for suggestions.
Can you tolerate the logging work to be lost? Only then should you start "background work" in an ASP.NET app.
QueueUserWorkItem will work. The more modern version is Task.Run. Make sure you catch errors that happen on that thread-pool thread. If not, you'll never find out about bugs and silently lose work.
If you expect a high volume of such calls, or expect them to take a long time, consider using async IO. It does not use any thread while in progress (not even a background thread).
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.
Is there a way to fire an Http call to an external web API within my own web API without having to wait for results?
The scenario I have is that I really don't care whether or not the call succeeds and I don't need the results of that query.
I'm currently doing something like this within one of my web API methods:
var client = new HttpClient() { BaseAddress = someOtherApiAddress };
client.PostAsync("DoSomething", null);
I cannot put this piece of code within a using statement because the call doesn't go through in that case. I also don't want to call .Result() on the task because I don't want to wait for the query to finish.
I'm trying to understand the implications of doing something like this. I read all over that this is really dangerous, but I'm not sure why. What happens for example when my initial query ends. Will IIS dispose the thread and the client object, and can this cause problems at the other end of the query?
Is there a way to fire an Http call to an external web API within my own web API without having to wait for results?
Yes. It's called fire and forget. However, it seems like you already have discovered it.
I'm trying to understand the implications of doing something like this
In one of the links in the answers you linked above state the three risks:
An unhandled exception in a thread not associated with a request will take down the process. This occurs even if you have a handler setup via the Application_Error method.
This means that any exception thrown in your application or in the receiving application won't be caught (There are methods to get past this)
If you run your site in a Web Farm, you could end up with multiple instances of your app that all attempt to run the same task at the same time. A little more challenging to deal with than the first item, but still not too hard. One typical approach is to use a resource common to all the servers, such as the database, as a synchronization mechanism to coordinate tasks.
You could have multiple fire-and forget calls when you mean to have just one.
The AppDomain your site runs in can go down for a number of reasons and take down your background task with it. This could corrupt data if it happens in the middle of your code execution.
Here is the danger. Should your AppDomain go down, it may corrupt the data that is being sent to the other API causing strange behavior at the other end.
I'm trying to understand the implications of doing something like
this. I read all over that this is really dangerous
Dangerous is relative. If you execute something that you don't care at all if it completes or not, then you shouldn't care at all if IIS decides to recycle your app while it's executing either, should you? The thing you'll need to keep in mind is that offloading work without registration might also cause the entire process to terminate.
Will IIS dispose the thread and the client object?
IIS can recycle the AppDomain, causing your thread to abnormally abort. Will it do so depends on many factors, such as how recycling is defined in your IIS, and if you're doing any other operations which may cause a recycle.
In many off his posts, Stephan Cleary tries to convey the point that offloading work without registering it with ASP.NET is dangerous and may cause undesirable side effects, for all the reason you've read. That's also why there are libraries such as AspNetBackgroundTasks or using Hangfire for that matter.
The thing you should most worry about is a thread which isn't associated with a request can cause your entire process to terminate:
An unhandled exception in a thread not associated with a request will
take down the process. This occurs even if you have a handler setup
via the Application_Error method.
Yes, there are a few ways to fire-and-forget a "task" or piece of work without needing confirmation. I've used Hangfire and it has worked well for me.
The dangers, from what I understand, are that an exception in a fire-and-forget thread could bring down your entire IIS process.
See this excellent link about it.
Sometimes there is a lot that needs to be done when a given Action is called. Many times, there is more that needs to be done than what needs to be done to generate the next HTML for the user. In order to make the user have a faster experience, I want to only do what I need to do to get them their next view and send it off, but still do more things afterwards. How can I do this, multi-threading? Would I then need to worry about making sure different threads don't step on each others feet? Is there any built in functionality for this type of thing in ASP.NET MVC?
As others have mentioned, you can use a spawned thread to do this. I would take care to consider the 'criticality' of several edge cases:
If your background task encounters an error, and fails to do what the user expected to be done, do you have a mechanism of report this failure to the user?
Depending on how 'business critical' the various tasks are, using a robust/resilient message queue to store 'background tasks to be processed' will help protected against a scenario where the user requests some action, and the server responsible crashes, or is taken offline, or IIS service is restarted, etc. and the background thread never completes.
Just food for though on other issues you might need to address.
How can I do this, multi-threading?
Yes!
Would I then need to worry about making sure different threads don't step on each others feet?
This is something you need to take care of anyway, since two different ASP.NET request could arrive at the same time (from different clients) and be handled in two different worker threads simultaneously. So, any code accessing shared data needs to be coded in a thread-safe way anyway, even without your new feature.
Is there any built in functionality for this type of thing in ASP.NET MVC?
The standard .net multi-threading techniques should work just fine here (manually starting threads, or using the Task features, or using the Async CTP, ...).
It depends on what you want to do, and how reliable you need it to be. If the operaitons pending after the response was sent are OK to be lost, then .Net Async calls, ThreadPool or new Thread are all going to work just fine. If the process crashes the pending work is lost, but you already accepted that this can happen.
If the work requires any reliable guarantee, for instance the work incurs updates in the site database, then you cannot use the .Net process threading, you need to persist the request to do the work and then process this work even after a process restart (app-pool recycle as IIS so friendly calls them).
One way to do this is to use MSMQ. Other way is to use the a database table as a queue. The most reliable way is to use the database activation mechanisms, as described in Asynchronous procedure execution.
You can start a background task, then return from the action. This example is using the task Parallel Library, found in .NET 4.0:
public ActionResult DoSomething()
{
Task t = new Task(()=>DoSomethingAsynchronously());
t.Start();
return View();
}
I would use MSMQ for this kind of work. Rather than spawning threads in an ASP.NET application, I'd use an Asynchronous out of process way to do this. It's very simple and very clean.
In fact I've been using MSMQ in ASP.NET applications for a very long time and have never had any issues with this approach. Further, having a different process (that is an executable in a different app domain) do the long running work is an ideal way to handle it since your web application is no being used to do this work. So IIS, the threadpool and your web application can continue to do what they need to, while other processes handle long running tasks.
Maybe you should give it a try: Using an Asynchronous Controller in ASP.NET MVC
Is it possible to return the page response to the user, before you've finished all your server side work?
Ie, I've got a cheap hosting account with No database, but I'd like to log a certain event, by calling a webservice on my other, more expensive hosting account (ie, a very slow logging operation)
I don't really want the user to have to wait for this slow logging operation to complete before their page is rendered.
Would I need to spin up a new thread, or make an asynchronous call? Or is it possible to return the page, and then continue working happily in the same thread/code?
Using ASP.Net (webforms) C# .Net 2.0 etc.
You would probably need a second thread. An easy option would be to use the ThreadPool, but in a more sophisticated setup a producer/consumer queue would work well.
At the simplest level:
ThreadPool.QueueUserWorkItem(delegate {
DoLogging(state details);
});
You sure can - try Response.Flush.
That being said - creating an asynchronous call may be the best way to do what you want to do. Response.Flush simply flushed the output buffer to the client, an asynchronous call would allow you to fire off a logging call and not have it impact the client's load time.
Keep in mind that an asynchronous call made during the page's life cycle in ASP.NET may not return in time for you to do anything with the response.
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.