Overriding continuation state storage/restore algorithm? - c#

When i saw the first news about await, i was very excited and i thought many ways of using it.
One of these is to use it in my web framework to hide the asynchronous aspect of client/server exchanges like it's done in several frameworks.
So here is the deal:
I would like to write things like that:
{
Page p = new Page();
FormResponse response = await p.Show();
var field1 = reponse.inputField["input1"];
...
}
I would like the dev to be able to write this code on the server. As you guess p.Show() write in the HttpResponse the html code displaying the page with the form, and send the response to the client, so, the thread is
killed and i never reach the next instruction (FormResponse response =).
So here is my question:
Is there any way of doing such a thing ? I know await cut the code, pack it in a continuation, make the closure for us, and store it somewhere to call it back when p.Show() is done.
But here, the thread is going to be killed, and this is my code which recieve the submit response from Page which has to deal with it. So i have to restore the continuation that "await" created and execute it myself.
Am i getting high or is it possible ?
Edit : additional infos
I can explain a bit more, but we need an example.
Imagine you want to make an async call to a webservice, you just use await and then call the webs.
A webs doesn't display any page, it returns pieces of information and you can continue the next instructions, so with a webs we have : Client -> Server A [-callwebs-> Server B ->] Server A -> Client.
Now, imagine a webs wich has to display a user interface to grab some information from the user, we can call this kind of webs a UIwebs (a reusable interface called by several webapp),
it displays the ui, grabs the info, and sends it back to the caller.
So with a UI webs we have : Client -> Server A [-response_redirect-> Client -get-> Server B (here is the UIwebs, the client inputs whatever) -response_redirect-> Client -get-> ] Server A -> Client
What i put between brackets has to be handle in the way by the developper :
so for a classic webs, i can imagine the asynchronous page is "sleeping" waiting the webs to response, but with a UI webs we have to response à redirect to the client, so the page is done for asp.net, and SynchronizationContext says that there is no more async instruction to wait for.
In fact, my need here is the same as turning on the web server, and sending a request to it wich coule restore everything needed to execute the code just after the await.
Regards,
Julien

I'm not sure what the problem is.
If you have, e.g., ASP.NET asynchronous pages, then any top-level (async void) function will properly notify ASP.NET that the page is incomplete and release the thread. Later, the continuation will run on a (possibly another) thread, restore the request context, and finish the request.
The async design was carefully done to enable this exact behavior. In particular, async void increments the outstanding asynchronous operation count in SynchronizationContext, as I described in a recent MSDN article.
If you're running your own host (i.e., not using ASP.NET), then you'll have to implement SynchronizationContext. It's non-trivial but not extremely hard, either. Once this is done, async and await will "just work". :)
Updated answer in response to edit:
Keep in mind that await/async are just syntactical sugar; they don't enable anything that wasn't possible before - they just make it easier.
If I understand your situation correctly, you want a web service to return a UI and then respond to it. This is an inversion of how HTTP works, so you'd have to do some funky stuff with viewstate. I'll think about it...

Related

Wrapping a non async-method (which does web calls) into async

I know you should only use async for stuff which is not "CPU-intensive", e.g. file writes, web calls etc. and therefore I also know it doesn't makes sense to wrap every method into Task.Run or something similar.
However what should I do when I know a method does a web call, but it doesn't offer an async interface. Is it in this case worth to wrap it?
Concrete example:
I'm using CSOM (Client SharePoint Object Model) in my WebApi application (server) and want to get a SharePoint list.
This is normally done like this:
[HttpGet]
[Route("foo/{webUrl}")]
public int GetNumberOfLists(string webUrl)
{
using (ClientContext context = new ClientContext(webUrl))
{
Web web = context.Web;
context.Load(web.Lists);
context.ExecuteQuery();
return web.Lists.Count;
}
}
And I thought about changing it to something like this:
[HttpGet]
[Route("foo/{webUrl}")]
public async Task<int> GetNumberOfLists(string webUrl)
{
using (ClientContext context = new ClientContext(webUrl))
{
Web web = context.Web;
context.Load(web.Lists);
await Task.Run(() => clientContext.ExecuteQuery());
return web.Lists.Count;
}
}
Does it make sense and does it help? As I understand it, I just create / need a new thread for executing the query ("overhead") but at least the request thread will be free / ready for another request (that would be good).
But is it worth it and should it be done like this?
If so:
Isn't it strange that Microsoft doesn't offer the "async" method out of the box or did they just not care about it?
edit:
updated to use Task.Run as suggested in comment.
However what should I do when I know a method does a web call, but it doesn't offer an async interface.
Unfortunately still somewhat common. As different libraries update their APIs, they will eventually catch up.
Is it in this case worth to wrap it?
Yes, if you're dealing with a UI thread. Otherwise, no.
Concrete example... in my WebApi application (server)
Then, no, you don't want to wrap in Task.Run. As noted in my article on async ASP.NET:
You can kick off some background work by awaiting Task.Run, but there’s no point in doing so. In fact, that will actually hurt your scalability by interfering with the ASP.NET thread pool heuristics... As a general rule, don’t queue work to the thread pool on ASP.NET.
Wrapping with Task.Run on ASP.NET:
Interferes with the ASP.NET thread pool heuristics twice (by taking a thread now and then releasing it later).
Adds overhead (code has to switch threads).
Does not free up a thread (the total number of threads used for this request is almost equal to just calling the synchronous version).
As I understand it, I just create / need a new thread for executing the query ("overhead") but at least the request thread will be free / ready for another request (that would be good).
Yes, but all you're doing is jumping threads, for no benefit. The thread used to block on the query result is one less thread ASP.NET has to use to handle requests, so freeing up one thread by consuming another isn't a good tradeoff.
Isn't it strange that Microsoft doesn't offer the "async" method out of the box or did they just not care about it?
Some of the "older" MS APIs just haven't gotten around to adding async versions yet. They certainly should, but developer time is a finite resource.
This is my personal view of your problem and for me the above way is not required. When we host your API in IIS, the server assigns one thread from thread pool it has in the server. The IIS also has a setting of maxConcurrentRequestsPerCPU maxConcurrentThreadsPerCPU. You can setup these values to serve the request instead of handling the request all by yourself.

Asynchronous calls to server using ASP .Net MVC 5 and AngularJS

I have one HTTP post call in angularjs which takes around 7-8 secs to complete the task. The url is action method of one controller in MVC. As it is taking a lot of time I don't want my user to wait for this operation but can navigate to any other page or even can continue with different operations on the same page. once the operation gets complete, it will notify user for either the success or failure.Currently any other http post waits for this post to get complete before showing it's respective result. I need help in what can be done for this scenario. What is the best approach? I checked this below link and I see some suggestions. Will it be helpful? link- http://tech.pro/tutorial/1252/asynchronous-controllers-in-asp-net-mvc
AngularJS Code-
$http({
url: key_Url_Generate,
method: Post,
params: $scope.PlanDetails
}).then(function (result) {
//Notify user for success or failure
}
Controller Action Method-
[HttpPost]
public ActionResult GenerateLtdQuote(LTD_PlanDetailsVM ltdPlanDetailsVM)
{
// time consuming operation here
}
No, async, at least in terms of C#, merely allows the thread to be returned to the pool while it is in a wait state, i.e. waiting for something like an external service to respond. It does not make the action return quicker. In fact, if anything async can make things slower, as it adds overhead. If the endpoint being hit by your AJAX does anything that puts the thread in a wait state, where it's doing nothing but waiting for some external process to complete, then you should use async on it, but only because it allows the server to more efficiently use resources. It won't make anything happen any quicker, though.
Async, in terms of JavaScript, is a little different, as JavaScript process will continue. That is why you have a callback for AJAX requests. When whatever resource is being accessed remotely finally responds, the callback will be invoked, but other things can still happen in the meantime. This actually makes your question more confusing, though, because by using AJAX, your page should not be blocked at all and the user should still be able to interact with the page and do whatever they want. The only way this wouldn't occur is if you're running AJAX synchronously, which is actually a little hard to do by accident, and should definitely be avoided.

Using Async controller action to call existing synchronous method

I've not dealt much with Async/threads/Tasks other than some web services.
I'm using MVC4. I have existing code which takes some time to run. It is using an existing method in the service layer, which uses various other the areas in further layers.
Essentially I was hoping to be able to make an ASync call from the Asynccontroller to that method. However it appears that I would need to change/create another method to implement all the Task & await keywords, quite a hefty job altering all the way down the chain.
Is it possible to call/'fire' a synchronous method in this manner?
I want the long process (creating some documents in the background) to continue running even if the user closes their browser. However if the user still has the browser open then I would like to return a notification to them.
Is there a better way to fire a background task to execute from the MVC Application?
I think you're trying to use async for something it cannot do. As I describe on my blog, async does not change the HTTP protocol.
Is it possible to call/'fire' a synchronous method in this manner?
Sort of. You can use Task.Run if you have CPU-bound work that you want to move off the UI thread in a desktop/mobile application. But there is no point in doing that in an ASP.NET MVC application.
I want the long process (creating some documents in the background) to continue running even if the user closes their browser. However if the user still has the browser open then I would like to return a notification to them.
The problem with this is that you'd be returning early from an ASP.NET request, and (as I describe on my blog), that's quite dangerous.
A proper solution would be to queue the work in a reliable queue (e.g., Azure queue or MSMQ), have an independent backend for processing (e.g., Azure worker role / web job or Win32 service), and use something like SignalR for notification.
As soon as you attempt to do work in an ASP.NET process without a request context, then you run into the danger that your process may exit without completing the work. If you are OK with this, then you can use the BackgroundTaskManager type from my blog above to minimize the chance of that happening (but keep in mind: it can still happen).

how to interrupt a long-running Web Service call

I am dealing with a web-service call that may take anywhere from a few seconds to several minutes to complete. It constructs the requested data and returns it. Right now for a long-running call into the WS the user interface (WinForms) becomes unresponsive; the user has no way to cancel the operation.
The ideal approach to solving this (I think) would be to break the operation into two web-service calls: first a request, second to get the status or available data.
But if the web-service structure cannot be changed, what is the best way to interrupt the web-service call?
UPDATE:
The WS call could be made asynchronously. If the user wants to cancel the operation, then I'd like to relieve the server of unfinished work (rather than letting the thread complete normally and throw away the response). Thread.Abort() is a possibility but I want to know if there is a better way.
The web services I am working with are WCF based. The operations are read-only, so there is nothing to undo if interrupted.
You can generate Asynchronous proxy class to implement this feature.
Please look at the following link for sample,
http://msdn.microsoft.com/en-us/library/wyd0d1e5(v=vs.100).aspx

Multi-threading required in ASP.NET websites?

I am building a simple ASP.NET website, which will receive SMSes via a 3rd party SMS API (through URL push), and then the website will acknowledge the senders by sending SMSes back to them. I am saving the incoming SMSes in a database. I have implemented the logic as below:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//declaring variables to be used elsewhere, but in this same class. I have just this one class.
//Grabbing the URL parameters here (contents of SMS).
//Saving SMSes in the database. Database interaction happening only inside Page_Load.
//Call these functions
SomeLogicFunction();
SendSMSFunction();
}
SomeLogicFunction()
{
}
SendSMSFunction()
{
}
}
Now, I have read somewhere that ASP.NET takes care of multi-threading and similar aspects. So, if I have a simple website like this, do I need to take care of multi-threading? Or Page_Load function/ASP.NET pretty much handles it automatically?
If the answer is I don't need to do anything, then its all awesome!
But if I have to take care of multi-threading, can you please help with some tips on how should I approach? I expect few thousand SMSes.
Thanks.
By default, for each request that comes in, ASP.NET grab a thread pool thread, make a new instance of your Page class, and call the appropriate Page_Load and event functions on that thread. It will use multiple threads for multiple requests simultaneously. Just be careful that any state you have in static members and fields is being properly shared and synchronized. Of course, avoid the shared state if possible.
ASP.NET and IIS will begin to reject requests if there are enough requests already being processed, so make sure your processing times are sufficiently fast. If you run into bottlenecks, you can increase the number of requests happening in parallel. If you have really high load (say hundreds of requests a second), there are asynchrony APIs you can use to increase the number of in-flight requests even further. But start out simple, of course, and you'll probably be fine.
In this particular case I think you would benefit from using Multi-Threading in your ASP.Net application.
Let me explain first how Multi-threading works in ASP.Net
ASP.Net provides a fixed number of threads to be used to handle requests, when the max number of threads have been used, incoming requests will be placed in a queue blocking potentially the web application. If incoming requests keep arriving to the server, you would end up with a Service Unavailable error.
Therefore one simple way to increase scalability in your application is releasing ASAP the threads used by ASP.Net to handle your request.
A way to do this, is to create an Async page (you could also create an Async HttpHandler), when you create an Async page, the long-time consuming process is placed in another thread, releasing almost immediately the ASP.Net thread. When your process has finished, a new thread will be used to instantiate a new instance of your page (the whole page life cycle won't be run though, meaning this process is cheaper) and finally the response will be sent to your client.
As you can see, since you release your ASP.Net threads almost immediately new incoming requests can be handled by ASP.Net
As an example, consider the following answer:
https://stackoverflow.com/a/11525692/1268570
The real question to ask in your case is that: Are the functions SomeLogicFunction() and SendSMSFunction() blocking or non-blocking? (i.e. do they block furthur code until the SMSes are sent or it resumes your Page_Load() processing while continuing to send messages asynchronously?
In case even one function blocks, then you will "have to" implement multithreading because you must create a separate thread for those functions to run parallelly while your Page_Load() processing is going on. OTOA, if they are non-blocking then ASP.NET will take care of them by running in separate threads if required or mandated by the framework.

Categories