views:

78

answers:

4

I've developed a program using Delphi that, among some features, does a lot of database reading of float values and many calculations on these values. At the end of these calculations, it shows a screen with some results. These calculations take some time to finish: today, something like 5 to 10 minutes before finally showing up the results screen.

Now, my customers are requesting a .Net version of this program, as almost all of my other programs have already gone to .Net. But I'm afraid that this time-consuming calculation procedure wouldn't fit the web scenario and the program would take the user to some kind of timeout error.

So, I'd like some tips or advices on how to do this kind of procedure. Initially I thought about calling a local executable (that could be even my initial Delphi program, in a console way) and after some time show the result screen in a web page. But, again, I'm afraid this wouldn't be the best approach.

+4  A: 

An external process is a reasonable way to go about it. You can fire off a thread inside the ASP.NET process (i.e. just with new Thread()) which could also work, but there are issues around process recycling and pooling that might make this a little harder. simply firing off an external process and then maybe using some Ajax polling to check on it's status on the browser seems like a good solution to me.

Dean Harding
@dean harding: the problem with this approach is that potentially you end up with loads of running threads (given you have enough users kicking of this calculation). A better (more scalable) approach is to put the request in a queue, and have a worker process process these.
Toad
@Toad: that's true, I guess it just depends on the expected workload.
Dean Harding
@Toad: But I could, e.g., set a flag on a table and block other users to start a new calculation thread until the first one has ended, isn't it? I'll give this idea a try, test it and later I come back here to vote the answers...
SoftwareSculptor
@softwaresculptor you can, but it is not very user friendly. Someone has to wait their turn, and retry after some time, maybe to find the slot has been taken again by someone else. Anyhow for low usage sites, the starting a thread way is fine. I was just pointing out the issues which might happen with his way
Toad
+3  A: 

FWIW, another pattern that some existing online services use (for instance, ones that do file conversion that may take a few minutes) is having the person put in an email address and just send the results via email once it's done - that way if they accidentally kill their browser or it takes a little longer than expected or whatever, it's no big deal.

Another approach I've taken in the past is basically what Dean suggested - kick it off and have a status page that auto-refreshes, and once it's complete, the status includes a link to results.

James Manning
A: 

How about:

  • Create a Web Service that does the fetching/calculation.
  • Set the timeout so it wont expire.

YourService.HeavyDutyCalculator svc = new YourService.HeavyDutyCalculator(); svc.Timeout = 10 * 1 * 1000; //Constitutes 10 mins, 10 mins x 1 second x 1000 ms Service.CalculateResult result = svc.Calculate();

Note that you can put -1 if you want it to run infinitely.

MSDN:

Setting the Timeout property to Timeout.Infinite indicates that the request does not time out. Even though an XML Web service client can set the Timeout property to not time out, the Web server can still cause the request to time out on the server side.

  • Call that web method inside you web page
  • Place a waiting/inProgress image
  • Register for web method OnComplete event; and show results upon complete.

You can also update the timeout in your web.config:

<httpRuntime useFullyQualifiedRedirectUrl="true|false"
             maxRequestLength="size in kbytes"
             executionTimeout="seconds"
             minFreeThreads="number of threads"
             minFreeLocalRequestFreeThreads="number of threads"
             appRequestQueueLimit="number of requests"
             versionHeader="version string"/>
KMan
@kman: and expect the user to silently wait for 10 minutes hoping something will happen? I'm not sure this is the best solution for a webbased app. Long running tasks should either be done in a separate thread, or even better, be put in a queue where a worker will pick it up and process it
Toad
@Toad: Even if you are using a thread, how do you plan to handle *10-minute-wait-state* of user? There is a step which says *Place a waiting/inProgress image* above, that handles just that. Also, Async web method calls handle the thread functionality internally; and the asynchronous implementation of a Web method frees up the worker thread to handle other parallel tasks that can be performed by the Web method; this ensures optimal utilization of the thread pool. Also, *to queue to not to queue* is not the question, the only way to minimize the time, is to lessen the time of data processing.
KMan
A: 

Regardless of what else you do you need a progress bar or other status indication to the user. Users are used to web pages that load in seconds, they simply won't realise (even if you tell them in advance) that they have to wait a full 10 minutes for their results.

Daniel