I have two web pages . In one page I am uploading some file and processing that data which takes lot of time to be completed. While on other page I am simply rendering the data on database.
I have implemented this application in c# mvc.
My requirement is that once user upload the file the file processing start in background and user would be able to navigate other pages.
Can we achieve this through asynchronous controller.
You are saying that processing the data takes a lot of time. Using an asynchronous controller, you will free up the web server to serve other requests, however the request will complete in the same time as it would when invoked synchronously. (source: https://msdn.microsoft.com/en-us/library/ee728598%28v=vs.100%29.aspx)
If you do not want your user to wait, add a job queue to your stack, tell the user that you've accepted the file and are processing it, and notify him when the operation completes.
There are many job queue implementations available in .NET, a concrete suggestion would depend on whether you're running on "full" .NET or .NET Core.
Using async controllers won't do what you want here, although you should still use them as a first step. Async controllers will just free up the server threads so that more requests can be processed, without async any long running operations will block the threads they're using and stop other requests being processed. If there are enough long running threads then other client requests will get rejected.
You'll also (or instead) need to look into a different mechanism to process the file, for example the API action could just put the file in a folder and another (non-web service) process could monitor that folder and pick up new files to process. Alternatively you could look at queuing or message bus technology, this adds more complexity but also gives you safety around queue processing.
The other thing to consider is how you report validation issues or errors back to the uploading client, you could do some checks in the API action but you'll probably still need to consider how to notify clients when an error occurs during processing of a file. How you best do this will depend on your system.
Related
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 have an Work Tracker WPF application which deployed in Windows Server 2008 and this Tracker application is communicating with (Tracker)windows service VIA WCF Service.
User can create any work entry/edit/add/delete/Cancel any work entry from Worker Tracker GUI application. Internally it will send a request to the Windows service. Windows Service will get the work request and process it in multithreading. Each workrequest entry will actually create n number of work files (based on work priority) in a output folder location.
So each work request will take to complete the work addition process.
Now my question is If I cancel the currently creating work entry. I want to to stop the current windows service work in RUNTIME. The current thread which is creating output files for the work should get STOPPED. All the thread should killed. All the thread resources should get removed once the user requested for CANCEL.
My workaround:
I use Windows Service On Custom Command method to send custom values to the windows service on runtime. What I am achieving here is it is processing the current work or current thread (ie creating output files for the work item recieved).and then it is coming to custom command for cancelling the request.
Is there any way so that the Work item request should get stopped once we get the custom command.
Any work around is much appreciated.
Summary
You are essentially talking about running a task host for long running tasks, and being able to cancel those tasks. Your specific question seems to want to know the best way to implement this in .NET. Your architecture is good, although you are brave to roll your own rather than using existing frameworks, and you haven't mentioned scaling your architecture later.
My preference is for using the TPL Task object. It supports cancellation, and is easy to poll for progress, etc. You can only use this in .NET 4 onwards.
It is hard to provide code without basically designing a whole job hosting engine for you and knowing your .NET version. I have described the steps in detail below, with references to example code.
Your approach of using the Windows Service OnCustomCommand is fine, you could also use a messaging service (see below) if you have that option for client-service comms. This would be more appropriate for a scenario where you have many clients talking to a central job service, and the job service is not on the same machine as the client.
Running and cancelling tasks on threads
Before we look at your exact context, it would be good to review MSDN - Asynchronous Programming Patterns. There are three main .NET patterns to run and cancel jobs on threads, and I list them in order of preference for use:
TAP: Task-based Asynchronous Pattern
Based on Task, which has been available only since .NET 4
The prefered way to run and control any thread-based activity from .NET 4 onwards
Much simpler to implement that EAP
EAP: Event-based Asynchronous Pattern
Your only option if you don't have .NET 4 or later.
Hard to implement, but once you have understood it you can roll it out and it is very reliable to use
APM: Asynchronous Programming Model
No longer relevant unless you maintain legacy code or use old APIs.
Even with .NET 1.1 you can implement a version of EAP, so I will not cover this as you say you are implementing your own solution
The architecture
Imagine this like a REST based service.
The client submits a job, and gets returned an identifier for the job
A job engine then picks up the job when it is ready, and starts running it
If the client doesn't want the job any more, then they delete the job, using it's identifier
This way the client is completely isolated from the workings of the job engine, and the job engine can be improved over time.
The job engine
The approach is as follows:
For a submitted task, generate a universal identifier (UID) so that you can:
Identify a running task
Poll for results
Cancel the task if required
return that UID to the client
queue the job using that identifier
when you have resources
run the job by creating a Task
store the Task in a dictionary against the UID as a key
When the client wants results, they send the request with the UID and you return progress by checking against the Task that you retrieve from the dictionary. If the task is complete they can then send a request for the completed data, or in your case just go and read the completed files.
When they want to cancel they send the request with the UID, and you cancel the Task by finding it in the dictionary and telling it to cancel.
Cancelling inside a job
Inside your code you will need to regularly check your cancellation token to see if you should stop running code (see How do I abort/cancel TPL Tasks? if you are using the TAP pattern, or Albahari if you are using EAP). At that point you will exit your job processing, and your code, if designed well, should dispose of IDiposables where required, remove big strings from memory etc.
The basic premise of cancellation is that you check your cancellation token:
After a block of work that takes a long time (e.g. a call to an external API)
Inside a loop (for, foreach, do or while) that you control, you check on each iteration
Within a long block of sequential code, that might take "some time", you insert points to check on a regular basis
You need to define how quickly you need to react to a cancellation - for a windows service it should be within milliseconds, preferably, to make sure that windows doesn't have problems restarting or stopping the service.
Some people do this whole process with threads, and by terminating the thread - this is ugly and not recommended any more.
Reliability
You need to ask: what happens if your server restarts, the windows service crashes, or any other exception happens causing you to lose incomplete jobs? In this case you may want a queue architecture that is reliable in order to be able to restart jobs, or rebuild the queue of jobs you haven't started yet.
If you don't want to scale, this is simple - use a local database that the windows service stored job information in.
On submission of a job, record its details in the database
When you start a job, record that against the job record in the database
When the client collects the job, mark it for delayed garbage collection in the database, and then delete it after a set amount of time (1 hour, 1 day ...)
If your service restarts and there are "in progress jobs" then requeue them and then start your job engine again.
If you do want to scale, or your clients are on many computers, and you have a job engine "farm" of 1 or more servers, then look at using a message queue instead of directly communicating using OnCustomCommand.
Message Queues have multiple benefits. They will allow you to reliably submit jobs to a central queue that many workers can then pick up and process, and to decouple your clients and servers so you can scale out your job running services. They are used to ensure jobs are reliably submitted and processed in a highly decoupled fashion, and this can work locally or globally, but always reliably, you can even then combine it with running your windows service on cloud workers which you can dynamically scale.
Examples of technologies are MSMQ (if you want to maintain your own, or must stay inside your own firewall), or Windows Azure Service Bus (WASB) - which is cheap, and already done for you. In either case you will want to use Patterns and Best Practices for Enterprise Integration. In the case of WASB then there are many (MSDN), many (MSDN samples for BrokeredMessaging etc.), many (new Task-based API) developer resources, and NuGet packages for you to use
I am currently trying to create an application which has a homepage. On this homepage there is a button which is going to run CPU intensive code and then display the results. As I stated in the title the application is using ASP.NET and C# not Windows Forms which some other websites I have looked at seem to suggest.
I am relatively new to C# and have not attempted this in any other programming language. I also have no code to show as I don't really know how to progress this.
It can run CPU intensive code on the server, yes. Note that this will typically block your web application from sending a response in a reasonable amount of time and the web application could appear to be frozen.
What type of CPU intensive code did you have in mind? There are many ways to handle this scenario.
By "CPU intensive" I assume you mean it will take a long time for the process to complete? In a web application anything that takes more than a few moments should be done asynchronously. In the request/response model of HTTP it's best (for a number of reasons) to respond quickly to a client making a request.
In the case of a long-running process, by "asynchronous" I do not mean using AJAX, as that's still a request/response like any other.
By "asynchronous" what I mean in this case is that you want to have a separate server-side process which handles the CPU intensive task, and the web application does nothing more than queue the task for running and check the status of the task when people look for it. Then it can report the results of the task after it's done.
So a basic overview of the architecture would be something like this:
A user in the web application clicks a button to "start the task."
The web application inserts a record into a database table indicating that the task has been queued (maybe with a user ID of who queued it, a time stamp, anything else you'll need to know).
A separate scheduled application (console application or Windows Service, most likely) is perpetually running. (Either using a timer in an always-running Windows Service or scheduled to run over and over, such as every few minutes, as a console application.) This application checks the database table for new queued tasks.
When the application sees a task, it marks it as "started" in the database (so subsequent runs of the application don't try to run the same task in parallel) and starts running it.
The web application can see the status of the task in the database table and display it to users who request it, so users can see that it's still running.
When the task is completed, the task record in the database table is updated and the result is stored somewhere. (Depending on what the result is. Data? In the database. A report file of some sort? Save as a file somewhere. That's all up to you.)
The web application can see the status of the task as completed and any other information recorded, and users can request to view the output of the task.
The main thing to remember here is to break up the responsibilities into two applications. The web application is for the purpose of providing a user interface. A web application is not suited for long-running background tasks. So that responsibility is moved to a separate application which is better suited for that purpose. The two applications coordinate via a shared database.
Hi,
I have a ASP.NET application where I have added a Webservice that contains a "fire and forget" method. When this method is executed it will start a loop (0-99999) and for every loop it will read a xml file and save it to the database.
The problem is that this action will take a couple of hours and it usually ends with a Thread Aborted exception?
I have seen that you can increase the executionTimeout and this is how :
<httpRuntime executionTimeout="604800"/>
<compilation debug="true">
But this does not help?
I have also tried to add a thread.sleep within the loop. If I set it to 500 it will go half way and if I set <100 it will just go a couple of 1000 loops before the thread aborted exception?
How can I solve this?
Don't run the loop inside the web service. Instead, have it in a console app, a winforms app, or possibly even a windows service. Use the web service to start up the other program.
A web service is basically a web page, and asp.net web pages are not meant to host long running processes.
This article does not directly answer your question, but contains a snippet of info relevant to my answer:
http://msdn.microsoft.com/en-us/magazine/dd296718.aspx
However, when the duration of the
operation grows longer than the
typical ASP.NET session duration (20
minutes) or requires multiple actors
(as in my hiring example), ASP.NET
does not offer sufficient support. You
may recall that the ASP.NET worker
processes automatically shut down on
idle and periodically recycle
themselves. This will cause big
problems for long-running operations,
as state held within those processes
will be lost.
and the article is a good read, at any rate. It may offer ideas for you.
Not sure if this is 'the answer', but when you receive the web service call you could consider dispatching the action onto another thread. That could then run until completion. You would want to consider how you ensure that someone doesn't kick off two of these processes simultaneously though.
I have a ASP.NET application where I
have added a Webservice that contains
a "fire and forget" method. When this
method is executed it will start a
loop (0-99999) and for every loop it
will read a xml file and save it to
the database.
Lets not go into that I fhind this approach quite... hm... bad for many reasons (like a mid of the thing reset). I would queue the request, then return, and have a queue listener do the processing with transactional integrity.
Anyhow, what you CAN do is:
Queue a WorkItem for a wpool thread to pick things up.
Return immediately.
Besides that, web services and stuff like this are not a good place for hourly long running processes. Tick off a workflow, handle it separately.
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.