I have a question in regard to running synchronous operations in an API design. I understand fully running asynchronous in certain scenarios like this is the correct approach this is more a conceptual understanding. If I have an Angular front end where the user can call an API endpoint with Subscribe which passes a list of CustomerId's. In the API a synchronous ActionResult is called which then iterates through these customer id's and calls a synchronous database call that can take a good amount of time to complete for each call.
The question I have is does that actually lock up the service if another user takes an action in the same UI against the backend service will the service not respond until that other user action is complete? I am just trying to wrap my head around that concept does the service lock up in that case and the UI would not be responsive. Multitask programming of course is the way to handle this just conceptually.
Thanks for input.
what you are missing is:-
angular runs on client end it means that every user will have an instance running on his system and his local instance may fail and in a result that particular client's instance may fail.
If using asynchronous backend it also won't stop it may fail the process and respond accordingly(if all errors have been handled). In the worst-case scenario even if it fails server gets restarted as mostly it's monitored using process managers like pm2. which takes no time to restart it.
so basically nothing gets blocked until there is an issue on your server and server stops to respond.
Related
It's my understanding that controllers get destroyed after an http request is made. Is there any assurances that the .NET Core runtime will wait until all threads initiated in an async action have terminated/ended before destroying the controller instance?
I have code below with an async controller action that calls an async function. I don't need to know if the async function actually succeeds or not (e.g. sending the email), I just want to make sure that it attempts to. My fear is that the .NET Core runtime will possibly kill the thread in the middle of execution.
Spoiler alert I ran the code below in my development environment and it does send the email every time (I put a real email). But I don't know if the behavior would change in a production environment.
Any thoughts/guidance?
[HttpGet]
public async Task SendEmail()
{
// If I would prefix this with 'await' the controller
// action doesn't terminate until the async function returns
this.InternalSendEmail();
}
private async Task InternalSendEmail()
{
try
{
await this.Email.Send("to#example.com", "Interesting subject", "Captivating content");
}
catch (Exception exc)
{
Log(exc);
}
}
What happens to the controller instance - nothing you can't manage
First, when we talk about destroying the controller instance let's be more precise. The instance won't get GCd as long as there's still a control flow that has access to this. It can't. So your controller instance will be fine in that regard at least until your private method finishes.
What will happen is your controller method will return and control flow will go to the next stage in the middleware chain, meaning your API consumer will likely get the http response before the email is sent. You will lose your HttpContext and all that goes with it when this happens. Thus if there's anything in your Log method or anything else in InternalSendEmail that relies on the HttpContext you need to make sure that information is extracted and provided to the background method before the controller method returns.
What happens to the thread - almost certainly nothing
As far as the thread goes, most likely the email will be sent on a different thread in the thread pool from that of the original controller method, but either way, no the .NET runtime isn't going to care about your controller method returning before every task it fired off has completed, let alone kill the thread. That's well above its paygrade. Moreover it's very rare for threads to be killed in any instance these days because it's not just your control flow that's affected but completely unrelated async contexts could be dependent on that thread too.
IIS Application Pool recycling and other things that COULD potentially kill your background task
The only reasonably likely thing that would cause your background task not to complete would be if the process terminated. This happens for example during an IIS Application Pool reset (or equivalent if you're using dotnet hosting), obviously a server restart, etc. It can also happen if there's a catastrophic event like running out of memory, or nasty things like memory faults unique to unsafe or native code. But these things would kill all pending HTTP requests too.
I have seen anecdotal assertions that if there are no pending HTTP requests it makes it more likely that IIS will recycle the application pool on its own even if you have other active code running. After many years of maintaining an application that uses a very similar pattern for many non-critical long-running tasks, I have not seen this happen in practice (and we log every application start to a local TXT file so we would know if this were happening). So I am personally skeptical of this, though I welcome someone providing an authoritative source proving me wrong.
That said, we do set the application pool to reset every day at 4 AM, so to the extent that IIS would be inclined to involuntarily reset our app pools (as it does need to happen every now and then) I suspect this helps mitigate that, and would recommend it regardless. We also allow only one CPU process per application, rather than allowing IIS to fire off processes whenever it feels like it; I suspect this also makes it less likely IIS would kill the process involuntarily.
In sum - this is perfectly fine for non-critical tasks
I would not use this for critical tasks where unambiguous acknowledgement of success or failure is needed, such as in life critical applications. But for 99+% of real world applications what you're doing is perfectly fine as long as you account for the things discussed above and have some reasonable level of fault tolerance and failsafes in place, which the fact that you're logging the exception shows you clearly do.
PS - If you're interested in having robust progress reporting and you aren't familiar with it, I would look into SignalR, which would allow you to notify the client of a successful email send (or anything else) even after the API call returns, and is shockingly easy to use. Plus an open websocket connection would almost certainly prevent IIS from mistaking a returned API method for an opportunity to kill the process.
Is there any assurances that the .NET Core runtime will wait until all threads initiated in an async action have terminated/ended before destroying the controller instance?
No, this is absolutely not guaranteed.
I don't need to know if the async function actually succeeds or not (e.g. sending the email), I just want to make sure that it attempts to. My fear is that the .NET Core runtime will possibly kill the thread in the middle of execution.
You cannot be sure that it will attempt to do so. The thread (and entire process) may be terminated at any time after the HTTP response is sent. In general, request-extrinsic code is not guaranteed to complete.
Some people are fine with losing some work (e.g., in this case, missing some emails). I'm not, so my systems are all built on a basic distributed architecture, as described on my blog.
It's important to note that work can be lost during any shutdown, and shutdowns are normal:
Any rolling upgrade triggers shutdowns (i.e., application updates).
IIS/ASP.NET recycles every 19 hours by default.
Runtime and OS patches require shutdowns.
Cloud hosting causes shutdowns (both at the VM level and higher levels).
Bottom line: shutdowns are normal, and shutdowns cause any currently-running request-extrinsic work to be lost. If you're fine with occasionally losing work, then OK; but if you require an assurance that the work is done, then you'll need a basic distributed architecture (a durable queue with a background processor).
There are more basic control flow issues with that logic what you trying to do. Your biggest problem is not the garantee about it is finished or not.
The example you present is very simple, but in real life example you will need some context in InternalSendEmail when it is executed. Because the request is completely served at the time it is executed, there will not be HttpContext, with all the consequences, for example you can not even log the IP address of the the request, not talking about all the more advanced context bound things like the user (or any other security principal) etc.
Of course you can pass anything as parameter (for example the IP address) but probably your logging infra (or your custom log enricher) will not work with that. Same is true for any other pipeline component which depends on the context.
I am working on SOAP-client in WCF to communicate with a self-hosted WCF service for remote controlling a piece of software that I am developing. This software has a very long running operation (lets call it Print) that will run for several minutes, perhaps up to an hour. I am trying to figure out how to implement the method Print given the following requirements:
The server should be able to raise FaultExceptions to the client, in case something goes wrong.
The client should be informed ASAP should the connection to the service be lost.
The server-side process of Print should continue to run if disconnected, so that the client can reconnect and continue to monitor the process and abort it if necessary.
Since I am new to WCF, I am unsure how to implement this. I currently see two alternatives:
Make Print an async method so that I can "fire and forget" it until it finishes or throws a FaultException. This seems straight-forward, but I see this "problem": There is a client-side request timeout in WCF with default value of 1 minute, which also applies to async methods (if I am not mistaken) and which I would therefore have to increase significantly. This seems a bit like a hack.
Implement the async behavior of Print myself by splitting its behavior into a non-async method StartPringing that starts a server-side task for printing and returns directly (or throws an exception in case something goes wrong) and a client-callback method PrintingFinished. I could then use the callback PrintingFinished to signal to the client, when the print-process has finished or a use an additional callback PrintingFailed to send an exceptions in case something goes wrong. This implementation would be "hidden" behind the async method Print, so that it behaves like any other async method that might throw an exception. Here I see the following challenge: I will have to implement the whole exception callback-stuff myself, to handle exceptions that occur after StartPringing has returned (from StartPringing itself I can throw FaultExceptions).
For both cases I will have to work out how to detect, when the connection is servered (which I am currently doing using a ping method on the service) and then somehow get that event to throw an exception from within the method Print. Implementation-wise this seems more aligned with alternative (2), since I need to already implement all the other event handlers for when the print-process finishes or an exception is thrown. However I am unsure how I would implement this for alternative (1).
So which one of the two alternatives is "better". By better I mean the following considerations:
1. Aligned with the "standard" way in WCF for implementing such a long running method.
2. Maintainability and extensibility.
If I should consider any other alternative, I would be grateful for any other suggestion.
For what I understand of your problem I think if you need a real async communication with reliability to use a message queue like MSMQ. You can use it with WCF : https://msdn.microsoft.com/en-us/library/ms789048(v=vs.110).aspx
Update
In your case, you can use a SOAP call to send print command to the server because it sync and you need to know if the server handle the request. After in the printing operation is long and async. When this operation finish (exception or not) it need to notify client(s). But client could be shutdown for example. For that communication a Message Queue is the solution, MQ ensure that the message will be transmit.
https://en.wikipedia.org/wiki/Message_queue
If you don't want use MSMQ, you can implement a web service on client side to be notified by the printing server, using for example a UUID to match call and notification in a map in memory or in a Data Base.
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).
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
I’m looking for the best way of using threads considering scalability and performance.
In my site I have two scenarios that need threading:
UI trigger: for example the user clicks a button, the server should read data from the DB and send some emails. Those actions take time and I don’t want the user request getting delayed. This scenario happens very frequently.
Background service: when the app starts it trigger a thread that run every 10 min, read from the DB and send emails.
The solutions I found:
A. Use thread pool - BeginInvoke:
This is what I use today for both scenarios.
It works fine, but it uses the same threads that serve the pages, so I think I may run into scalability issues, can this become a problem?
B. No use of the pool – ThreadStart:
I know starting a new thread takes more resources then using a thread pool.
Can this approach work better for my scenarios?
What is the best way to reuse the opened threads?
C. Custom thread pool:
Because my scenarios occurs frequently maybe the best way is to start a new thread pool?
Thanks.
I would personally put this into a different service. Make your UI action write to the database, and have a separate service which either polls the database or reacts to a trigger, and sends the emails at that point.
By separating it into a different service, you don't need to worry about AppDomain recycling etc - and you can put it on an entire different server if and when you want to. I think it'll give you a more flexible solution.
I do this kind of thing by calling a webservice, which then calls a method using a delegate asynchronously. The original webservice call returns a Guid to allow tracking of the processing.
For the first scenario use ASP.NET Asynchronous Pages. Async Pages are very good choice when it comes to scalability, because during async execution HTTP request thread is released and can be re-used.
I agree with Jon Skeet, that for second scenario you should use separate service - windows service is a good choice here.
Out of your three solutions, don't use BeginInvoke. As you said, it will have a negative impact on scalability.
Between the other two, if the tasks are truly background and the user isn't waiting for a response, then a single, permanent thread should do the job. A thread pool makes more sense when you have multiple tasks that should be executing in parallel.
However, keep in mind that web servers sometimes crash, AppPools recycle, etc. So if any of the queued work needs to be reliably executed, then moving it out of process is a probably a better idea (such as into a Windows Service). One way of doing that, which preserves the order of requests and maintains persistence, is to use Service Broker. You write the request to a Service Broker queue from your web tier (with an async request), and then read those messages from a service running on the same machine or a different one. You can also scale nicely that way by simply adding more instances of the service (or more threads in it).
In case it helps, I walk through using both a background thread and Service Broker in detail in my book, including code examples: Ultra-Fast ASP.NET.