Question

Sorry if this is quite a long question, i need some advice on what people consider to be the best method (as there are a few).

At the moment, my project has a method

do_job(jobid,userid)

This method take a minute or two, and then redirects to another page.

This has been rewritten so that it now runs in the background and redirects to another page whilst the thread which do_job is on continues. - This works fine.

In a button_click event in a default.aspx page :

Dim d as New do_job_delegate(AddressOf do_job)
d.BeginInvoke(jobid,userid, New AsyncCallback(AddressOf Callback),d)
Response.redirect("results.aspx")

Which relates to

Delegate Sub do_job_delegate(Byval jobid as integer, Byval userid as integer)

Public Sub do_job(Byval jobid as integer, Byval userid as integer)
     ' Do something for several seconds
End Sub

Public Sub Callback(Byval ar As IAsyncResult)
    ar.AsyncState.EndInvoke(ar)
End Sub

This basically does what i want, a user can carry on doing things on the site and the do_job method runs in the background and completes its tasks successfully.

However, i've now added to this do_job method, and there are several small tasks, each taking 30 or so seconds within do_job, and they could/should be made to run parallel. e.g

Public Sub do_job(Byval jobid as integer, Byval userid as integer)
     loop through between 1 or more (up to roughly 10 items)
         'process that takes about 30 seconds
     end loop
End Sub

So what i want to happen is - the longest time that do_job takes is the longest time of the longest job (30 seconds), rather than - 30 seconds x number of jobs = time it takes at the moment.

As i'm already using a delegate to detact the process from the ui, can anyone provide any advice/best practice on how i should rearrange my do_job method so that it can handle concurrent tasks to further boost the overall speed.

Thanks!

Was it helpful?

Solution

I would recommend that before you spend a bunch of time on this that you consider moving the work to a separate service rather than running it inline on your web server.

Just throw a record into a db table and have the service watch it.

Here is an article from Phil Haack explaining why you shouldn't mess with threads on your web server.

http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx

As far as executing the tasks in parallel, look at the .net 4.0 Parallel libraries. They make this kind of thing super easy.

http://msdn.microsoft.com/en-us/library/dd460717.aspx

OTHER TIPS

As @BNL said, this should really be done in a service or other process that exists outside of the web request/response pipeline. A potentially crippling issue with your current approach is that, if you get a lot of traffic, you're going to spawn a lot more threads than your system can reasonably handle. This eliminates whatever benefit you might have gained from multithreading in a single user environment, and, in fact, can add so much overhead that it causes a slower response than a single-threaded approach.

Consider putting a description of the task that has to be completed in a database table:

id
job_id
user_id
date_created
date_started
date_completed
status_code

and have your service poll that table to find jobs that need to be handled. This gives you a number of additional benefits, including the ability to generate a report of success/fails, job queuing that will persist across IIS resets, etc. If the web application needs to alert the user when a job is completed, have it check the table on page load (easy) or periodically via a AJAX request (less easy), like StackOverflow does when checking for new responses to a question you're reading.

See this article for an overview of creating services in VB.NET.

Failing that, an easy way to launch a lot of similar tasks in parallel is via Parallel.For and Parallel.ForEach, but I can't stress enough how dangerous this is in a web or other multi-user environment.

Also, you should distinguish between the ASP.NET version and the .NET framework version. Many/most servers should have the .NET framework 4 available even if their sites are using ASP.NET 2.

See this MSDN article for an example of the latter, but a service is really the way to go.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top