I’ve been working on redesigning a page for a web application that deals with massive number crunching which takes a long time to process. The calculations and data gathering and all the manipulation of data takes about 6 seconds. That might not seem like a long time but when you click a link to a page and that page takes 6-7 seconds to load it feels like an eternity and because the code is in the Page_Load method of the page nothing displays on the screen until the processing is complete.
So what do you do when you want a ton of data to process but not block your page from loading but also not require the user to have to press any buttons or interact with the page other than just loading it ?
Here’s the scenario and my result I implemented
About 85,000 rows of data are checked and calculated for company data, and average data. Another 100,000 records are checked in another table for company hours. All this data is then calculated against a formula to spit out a specific number to rank companies standings against an average over 7 years on a set of charts that are dynamically generated.
This process originally took about 30-45 seconds and would cause server timeouts and other errors.
After rewriting the SQL query and reducing the number of database calls it was still taking ~6 seconds.
So how to create a solution that would allow the page to load the initial body and then crunch all the data for the user with a nice little loading graphic while the processing happens in the background ?
The first step was to isolate all the code that was processing data and running in Page_Load off to another method.
Once you have that you have 2 options. You can implement threading and pass the heavy processing off to another thread but that is much more messy and it requires you to know if any certain data relies on other data that might be processing in a separate thread and needs to complete first before other code runs etc etc. It gets messy and hard to implement especially once you involve charting and some charts depend on data from other charts.
The simpler solution I found was to wrap up all my code that processes my data and draws my charts into its own method and then stick a Timer control on my page.
The timer control is very simple to use it takes an interval parameter for how long to wait before doing something and has an event for Timer_Tick that fires when the interval elapses.
The timer control runs in a loop and fires the Tick event each time it elapses.
<asp:Timer ID=”Timer1″ runat=”server” Interval=”100″ OnTick=”Timer1_Tick”>
</asp:Timer>
The interval is measured in milliseconds so 1000 is 1 second.
If you only want the timer to tick once and run its code in the event and stop then you can disable the timer as soon as it fires the event with Timer1.Enabled = false;
After that just call your method that has all your heavy processing and the timer will run after the elapsed interval time once the page has loaded.
To jazz it up and include an animated loading gif to show your users that data is loading for them you can add a div and put the image in it. add attributes to the div for id and add runat=”server” to allow you to get a reference to the div from .cs code behind with the id.
EX: <div id=”loadingdiv” runat=”server”>
cs codebehind:
loadingdiv.Visible = false;
Simply show the div with the loading graphic by default when the page loads and when the timer_Tick method completes on the last line hide the div and show your data or charts.
Here’s 2 links to sites that allow you to generate your own custom animated loading .gif files
If there are other ways to entertain partial page rendering after page load with no user interaction I’d like to hear about them !