ASP.NET MVC, ASP.NET Tips: Provide immediate feedback to the browser on Long Running Tasks – using IFrame and web handlers

Download to download the source code please click here


The <iframe> tag defines an inline frame that contains another document and is supported in all major browsers.
Internet Explorer Firefox Opera Google Chrome Safari

The <iframe> can be placed anywhere in the document flow. The iframe properties such as  height and width can be easily modified by CSS and JavaScript. Data can be passed back and forth between the parent container and iframe using Javasrcipt. The document that is displayed inside an iframe can access the main window by the parent keyword. Iframe can have their own source URL that is distinct from the parent page and we are interested on this feature. We first declare an Iframe in the page and keep it hidden. We then point the Iframe to our preferred web handler, during page load iframe initiate a request to the server and the server start the lengthy task, and flushes state change information. The server flushes the response wrapped inside <script> tag to perform DOM manipulation on the parent container – similar technique that we have seen in one of my post earlier. Here are the steps to follow.

  1. Declare Iframe in the page.
  2. Hide the Iframe.
  3. Point the src of the Iframe to the web handler.
  4. Get Iframe to initiate request from the the browser client to the web server when the page loads.
  5. Get the web handler to flush response on task state changes.
  6. Perform DOM manipulation on the parent container.


 Iframe

Here I have declared two javascript functions in the parent page – “updateContent” and “hide”. “UpdateContent” replaces the data on “ReportDiv” element. “Hide” hides the loader image when lengthy task ends. Then down below on the same page I have declared the iframe tag, pointed the src of the iframe to a regular web handler “JsWrappedDataHandler.ashx”, and used the style elements to hide the iframe. Lets look at the web handler and what is cooking there.

jswrappedhandler

This is a regular web handler and you may be wondering why am I sending 256 dummy bytes. This is a workaround to make IE work properly because IE accepts a message from the server after the first 256 bytes.

This technique is handy when we do not know about the message size and we can avoid any unexpected event by sending 256 dummy bytes before sending the – message.

Next thing to look at is the script block – where it invokes the javascript functions that we have defined in the parent container. Example "window.parent.updateContent", "window.parent.hide".

Finally the server flushes the response directly to the browser. The Iframe receives the progressive flushed response chunk/script block and executes the javascript code – which invokes the javascript functions from the parent container and updates the content of of “ReportDiv” element until the task completes.

The end user gets immediate feedback on task state changes and do not need to wait until the entire response download. When the task is complete it invokes the "hide" function to hide the loader image. This is what it looks like.


 iframefeedback

 

Asynchronous web handlers

I discussed a little bit about asynchronous web handlers  in earlier post and I promised that I will talk about it later – so I do so. It is recommended to use asynchronous web handlers for long/ lengthy tasks. An asyncchronous web handler implements IHttpAsyncHanddler – this means it implements two additional methods BeginProcessRequest and EndProcessRequest. The idea here is to spawn custom threads by hand to run the lengthy portion of the task and not block important ASP.NET work threads from the threadpool. I have discussed about why we should spawn an additional thread in great length in this post, and I am not going to go through that again here, I am jumping straight in to the implentation of Asynchronous web handler.

IframeAsyncPage

This page is exactly same as the first one in this post where I declared 2 javascript function in the parent container such as “undateContent” and “hide”. The only difference is the iframe is now pointing to a different web handler and this time an asynchronous handler.

jswrappedAsynchandler

Here this asynchronous web handler implements the IHttpAsyncHandler. The BeginProcessRequest performs all the lengthy bits inside request.BeginProcessRequest method asynchronously and signals when the task is completed. This executes the EndProcessRequest method. The AsycWebHandlerRequest class is a custom hand written class and I paste the code below.

AsyncwebhandlerRequest

Here I spawn custom Threads by hand to invoke the LongTask method. Long task has exact same code as we have seen in the regular web handler ProcessRequest method above, except the last line where it signals that the task is complete by invoking "requestState.CompleteRequest" method. Here the Response.Flush method does all the hard work to notify the connected browser about the task state changes and end user can enjoy immediate feedback from the server. You may be wondering about the AsyncRequestState class. I have used the exact same class during implementation of the Asynchrounous Page and can be found here.

I have indicated earlier that a web handlers is recommended for performance critical web pages. I have done some load tests to compare the result of regular web handler, asynchronous web handler and the asynchronous page that pretty much does the exact same operation. The test result of load tests that I have performed in exact same environment can be found below.

IframeAsync

Fig: Load test of Iframe and asychronous web handler that uses custom thread

IframeRegular

Fig: Load test of Iframe and regular web handler

WebPageAsync

Fig: Load test of asynchronous web page that implements custom thread

You can see that the asynchronous web handler that spawns custom thread is the clear winner. And when you compare Asynchronous page with web handler – we see web handler is superior.

Please note that the different techniques that I have been discussing  in last several posts  is also known as Comet that describe the web application model in which a long-held HTTP request allows a web server to push data to a browser, without the browser expicitly requesting it. However holding a connection open for infinite period has negative impact on browser usability. The problem is the javascript will keep accumulating and the page will have to preserve them in the page itself, resulting in a unbound page size and memory implications – at worst the page becomes totally unresponsive and will crash the browser. These is ok to choose for long task that has a definite end, however we need to be a bit careful when it comes to a “real-time” applications that keeps running for indefinite period. For example an airlines time table,

For a “real-time” application ( i.e. chat application, airline timetable ) a polling / long polling mechanism is more suitable where the server keeps looping for infinite period – produces the latest content and store it in a persistent layer – example a database/file, or in the application memory. The browser polls the latest response periodically, performs DOM manipulation to updates the page – and the user gets to see the latest record. Lets look at the polling techniques in my next post.

ASP.NET MVC, ASP.NET Tips: Provide immediate feedback to the browser on Long Running Tasks – using XMLHttpRequest call

XMLHttpRequest (XHR) is a DOM API that can be used inside a web browser scripting language, such as JavaScript, to send an HTTP or an HTTPS request directly to a web server and load the server response data directly back into the scripting language. The technique that we are going to discuss here takes advantage of XMLHttpRequest objects readyState == 3 status (Interactive – Downloading) and responseText property to perform DOM manipulation in a browser. Here is how it works

  1. A request is initiated from the the browser client to the web server using the XMLHttpRequest object.
  2. The webserver flushes response during task state changes.
  3. XMLHttpRequest object holds partial data in responseText property when readyState is 3 ( Interactive – Downloading ).
  4. DOM manipulation is perfomed during readystate == 3 to interactively update the web content.

 

Download to download the source code please click here

 

Please note that XMLHttpRequest based technique will not work in all browsers. Microsoft clearly mentions in the specification that – “readyState =  3, some data has been received. responseText is not available. responseBody is not available.” So this will not work in IE. However I found it working in Firefox and Chrome. Here is the code.

XmlHttpRequest

Here I have created a XmlHttpRequest object and configured it to perform a GET request to my DataHandler.ashx that I have created earlier. The piece of code that does the magic to notify the browser on state changes is the part where I am updating the content of “ReportDiv” element with req.responseText when req.readyState == 3. The responseText dynamically loads the flushed response and this piece of code updates the content of the browser. Then finally I hide the loader image when the req.readyState turns 4 that means – loaded, all the data has been received. This entire process is initiated by the getData() method which is invoked during the pageload even, but you can do the same on onclick of a button or anchor tag or by raising some other event that suits your need. For a refresher on what is happening inside DataHandler.ashx here is the web handler codes.

RegularHandler

The web handler simulates a long running task by putting the Thread to sleep. However it keeps flushing the response when the browser is connected to the server, until the task is complete. Please check my earlier post where I have done detailed discussion on Response.IsClientConnected property, Response.Flush method etc.

You may be wondering that this is still not the perfect solution that we are looking for as responseText is not available during readyState==3 in all browsers, we cannot do much about this however we can implement the IFrame Call that works in most of the browsers. Lets look at that.

ASP.NET MVC, ASP.NET Tips: Provide feedback to the user on Long Running Tasks – using loader image – MS AJAX and JQuery

It is quite common to display a loader-image or some kind of progress bar image in a browser when the server is busy serving the request. Before we go deep into page streaming techniques with XMLHTTPRequest call and IFrame, lets look into a simple loader icon implementation – the idea is to display “loading” image until the task completes, display the response in the browser when task ends and hide the loader image.

loading

Download to download the source code please click here

 

Invoke a long task and display loader image to notify task progress – using MS AJAX

Normally in a ASP.NET page we drop the ScriptManager control, put a reference of the webservice that we want to point to. The Scriptmanager goes and creates necessary proxy class for the webmethods. We can also add static methods to an ASP.NET page and qualify them as web methods and invoke them using javascript. This tutorial shows how to do all these by configuring the ScriptManager easily. However I will play with the Sys.Net.WebRequest class directly here. The Sys.Net.WebRequest provides the script API to make Web request. It becomes handy when we need to partially update a little section of the page and it is quite straight forward to use the Web Request class anyway. 

 

msajax

It may look like a lots of code above but when you look closely you find that all I have done is setup a get request to asynchronously invoke my DataHandler.ashx web handler that I created earlier. During page load the “PageLoad” method is called and this initiates the entire process. You can also do the same on the onclick event of an input button or anchor tag or by raising some other events that you prefer. The image that I used for the loader has been generated from this website Ajaxload.info,  this website has some nice loader image designs available. You can choose your indicator, background color, foreground color and generate your preferred loader. The webrequest invokes the web handler and the loader image is displayed until the full response is available. I populate the “ReportDiv” element with the completed response data, and hide the loader image with loader.style.display = “none”. There is also some codes above that handles timeout and abort situations.

 

Invoke a long task and display loader image to notify task progress – using JQuery

The JQuery based implementation of the same above is even more simpler and is done with a lot less coding.

Jquery

All I do here is I configure HTTP GET request call to my DataHandler.ashx inside the “$(document).ready” function -this function is infact the first thing to learn about jQuery if you are new to JQuery. If you want an event to work on your page, you should call it inside the $(document).ready() function. Everything inside it will load as soon as the DOM is loaded and before the page contents are loaded. If you have not worked with JQuery yet I would strongly recommend to have a look at it. The getData() function makes the HTTP GET call to the web handler and on success I put the response to the “ReportDiv” element. Then I hide the loader icon with style display = “none”;

Thats pretty much it, however this is not a robust solution and I am writing all the post in this series to render realtime states of a task in the browser. When we use this technique all we can display is the loader image to notify users that server is busy processing his/her request – we cannot display any real time update on the tasks state changes to the browser. The MS AJAX and JQuery web request calls do not allow to check XMLHttpRequest s readyState==3 status (will discuss about XMLHttpRequest object in the next post ). The web applications are stateless and request can only be initiated from the client, however XMLHttpRequest or a IFrame call can initiate a parallel request to the server and we can take advantage of that to stream contents to the browser. Lets look at them.

ASP.NET MVC, ASP.NET Tips: Provide immediate feedback to the browser on Long Running Tasks – in Asynchronous ASP.NET pages

Download to download the source code please click here

In the earlier post we have discussed little bit about the limited number of worker threads available in the thread pool of ASP.NET and we identified why we should always try to avoid to block those important worker threads. ASP.NET 2.0 introduces Asyn=”true” attribute in the page to handle asynchronous scenarios and under the hood this attribute tells ASP.NET to implement IHttpAsyncHandler in the page. There are more than one ways available in ASP.NET 2.0 and ASP.NET 2.0 (plus) to register asynchronous tasks in the page,

  • by AddOnPreRenderCompleteAsync method.
  • by declaring PageAsynTask tasks and register them by RegisterAsyncTask method.


However PageAsyncTask provides some extra flexibility over AddOnPreRenderCompleteAsync method, for example

  • it offers a timeout option.
  • allows to register more than one async task.
  • allows to configure async tasks to be executed in parallel or sequentially
  • RegisterAsyncTask passes HttpContext.Current to the End and Timeout methods
  • RegisterAsyncTask allows to pass object state to the Begin methods.

Lets look at how we can implement an asynchronous page to serve our scenario that we are focusing here, that is, to run long tasks asynchronously and at the same time provide immediate feedback to the browser. 

AsyncPageAspx
Fig: aspx page

AsyncPage

Fig: code behind

Here in the above code block I have left the AddOnPreRenderCompleteAsync code commented which can be used alternative to PageAsyncTask object & RegisterAsyncTask method. I have registered a PageAsyncTask task using RegisterAsyncTask method.  The “task” object is configured to point to – BeginAsyncOperation, EndAsyncOperation and TimeoutAsyncOperation functions. The BeginAsyncOperation does all the lengthy bits inside request.BeginProcessRequest() method and signals when completed, this executes the EndAsyncOperation method. However if the lengthy task is not completed within the timeout period, the TimeoutAsyncOperation executes.  Lets look at the AsyncRequest class now.

 AsyncRequest

The most important thing to note here in the above piece of code is, I spawn an additional custom thread by hand and I execute the lengthy bits i.e. the “Process” Method in the custom thread. The Process method simulates the lengthy task by putting the thread to sleep. However note that the Response.Flush() does the magic to notify the connected browser about the task state immediately. It is a good idea to always check the Response.IsClientConnected property we discussed this in length in one of our earlier post.

As soon as the lengthy task completes I call the CompleteRequest method of the requestState object.

 

AsyncRequestState
The CompleteRequest singnals that the asynchronous task is complete and it invokes the the callback method if available. In this example the callback invokes EndAsyncOperation method that we have configured in our PageAsyncTask object.

You may be wondering why I had to spawn a custom thread to run the lengthy operation where we can simply use asynchronous delegate invocation. You must know that Delegate.Invoke consumes worker thread from the ASP.NET thread pool. Even though the page releases a worker thread into the pool but immediately that thread ( or another worker thread ) is again taken from the thread pool. Now this precious thread is occupied until the long task finishes hence you gain nothing rather add overhead of switching thread from the pool. 

Fritz Onion in his popular article “Use Threads and Build Asynchronous Handlers in Your Server-Side Web Code” mentioned the same, “Asynchronous delegate invocation completely defeats the purpose of building an asynchronous handler because it draws from the same process-wide CLR thread pool that ASP.NET uses to service requests. While the primary request thread is indeed returned to the thread pool, another thread is taken out to perform the asynchronous delegate execution, which means that there is a net gain of zero threads for servicing additional requests, rendering the handler useless. You will run into the same problem if you use ThreadPool.QueueUserWorkItem to perform the asynchronous request processing because it also draws threads from the same process-wide CLR thread pool”.

Jeff Prosise also quoted him in his article by saying “Asynchronous delegates, are counterproductive in ASP.NET applications because they either steal threads from the thread pool or risk unconstrained thread growth. A proper asynchronous page implementation uses a custom thread pool, and custom thread pool classes are not trivial to write.

He also warned about it in his conclusion “A final point to keep in mind as you build asynchronous pages is that you should not launch asynchronous operations that borrow from the same thread pool that ASP.NET uses. For example, calling ThreadPool.QueueUserWorkItem at a page’s asynchronous point is counterproductive because that method draws from the thread pool, resulting in a net gain of zero threads for processing requests”.

After all these warnings if you were still implementing the frequently recommended asynchronous delegation invocation ( unfortunately, most of the google search result on this topic of asynchronous programming in ASP.NET will lead to an implementation of asynchronous delegation ) it would look something like this:

asyncdelegate

I do not want to discuss about delegate invocation because it completely defeats the purpose of implementing Asynchronous pages. I have done some load testing on the above two implementations and found the following result:

testresultdelegateinvocation

Fig: Load test result of asynchronous handlers with a delegate.

 

testresultthread

Fig: Load test result of asynchronous handler with custom thread.

Clearly we see that we gain significantly on asynchronous handler that uses custom thread in both cases,

  • requests/sec_total and
  • avg. Respons_Total.


I got distracted a bit from our original subject matter again, but it was worth doing this one. I have already discussed here how we can run long running task asynchronously and how to provide immediate feedback to the connected browser immediately. In this post and previous posts I was implementing solutions by taking advantage of ASP.NET page and web handlers however we can also give immediate feedback to clients using MS AJAX, JQuery, XMLHTTPRequest, IFrame etc. in ASP.NET pages. Lets look at them one by one.

ASP.NET MVC, ASP.NET Tips: Provide immediate feedback to the browser on Long Running Tasks – by streaming regular ASP.NET page

Here in this series of post I am discussing few techniques to give client instant feedback on task progress in ASP.NET page. In the previous post I have discussed about displaying task progress – using regular handler, here I will discuss how to do the same in standard asp.net page.

Download to download the source code please click here

Display task progress – in standard asp.net page

In this technique we write some regular ASP.NET script in the page itself, that performs streaming to the original page response directly. We put the lengthy task related code in the page and keep flushing the response when task state changes. The data is pushed to the the pages outgoing stream and the browser immediately displays the output. The connection to the browser is kept open until the task is complete.

PageStream

 

You see above I have written a regular ASP.NET page with some C# scripts that simulated a long running task by forcing the thread to sleep. However before the thread goes to sleep it Flushes the response using Response.Flush method.  I discussed about the Flush method in earlier post. It basically facilitates to send buffered output to the browser immediately. The other thing to note here is the the Response.IsClientConnected property which indicates the server whether the browser is still connected or not. The Response.IsClientConnected property can determine if the browser is still connected. So when we perform a lengthy operation it is a good idea to periodically test  whether the browser is still connected.

You may have already noticed that I am writing embedded javascript codes that manipulates the DOM. In this case this the ReportDiv elements innerHTML is assigned to latest flushed response. However to keep this example simple, I have been flushing the “report” string over and over again to reflect the changes in the browser and the same data is sent across the wire over and over. This may not be a good idea when you are flushing out a large report with 1000 records. You can reduce the amount of response traffic just by sending the progressive latest content only. To do this you will need to change your DOM manipulation code to perform append instead of replacement. Something like below.

PageStreamOptimized

Note that I have changed the codes to flush progressing latest content only, I have also modified the rendered javascript codes that is now appending latest flushed content to the existing content instead of replacement.

The above example is serving the long task in a regular synchronous manner however It is a good idea to implement long running tasks asynchronously, lets look at that in the next post.

ASP.NET MVC, ASP.NET Tips: Provide immediate feedback to the browser on Long Running Tasks – using regular web handler

As an ASP.NET developer we frequently deal with long running tasks for example:

  • Making long-lasting webservice calls.
  • Making prolonged calls to database that runs complex queries.
  • Do lengthy file operation
  • Calling remote objects etc.

When the server is busy performing the lengthy time consuming task/tasks, the poor user has to wait for the response. The most common technique used to interact with user is to display a loader icon or show some kind of progress bar on the page until the task is complete. However we can provide user immediate feedback of the task progress/state while the task is running in the Server and make the page more interactive/informative.

 

 iframefeedback

Here we will discuss several techniques to give end user instant feedback on the browser about task progress in  ASP.NET pages.

such as display:

 

Download


Display task progress using regular web handler:

This is very easy to code, all we need to do is write a regular web handler that runs the long running task and we have to keep flushing the response when state changes, in other words we decide to flush when the task reaches certain stage. The data is pushed to the the outgoing stream and the browser immediately displays the output. The connection to the browser is kept open until the task is complete.

RegularHandler

We have created a regular web handler that inherits from IHttpHandler and simulated a long running task by forcing the thread to sleep. However before the thread goes to sleep it Flushes the response using Response.Flush() method. The Flush method sends buffered output immediately. Normally all of the response is sent to the browser only when page completes its processing. This may be a issue for a long running task as the end user will not see anything until the page is complete. The Flush method comes handy in this situation and can send buffered output periodically to the browser. Imagine you will have to display 500 records and you can flush the buffer every 20 records until it is complete. The good thing of doing this is – user can see some data immediately, visualize the progress of the report and the server memory is also released on every Flush operation.

One more thing to note is the Response.IsClientConnected property which indicates the server whether the browser is still connected or has already left.  A very common scenario is user starts the long expensive task but decided to close the browser before the task is complete. When a browser requests the page from the server but does not wait for the entire page to be downloaded, the server continues to process the request, wasting CPU cycles. The Response.IsClientConnected property can determine if the browser is still connected or not. So when we perform a long task it is always a good idea to periodically test  whether the browser is still connected or not.

UseHandler 
A web handler file works just like a aspx page and can be directly browsed via a browser. The web handler above, returns response type text/html and we have pointed an anchor tag to the web handler. Please note a web handler is recommended for a performance critical web page.

I have started with a regular synchronous web handler, however it is recommended to use asynchronous web handlers that implements IHttpAsyncHandler for long running tasks. ASP.NET has limited number of threads in the thread pool and a normal synchronous page holds on to the thread for the duration of the request, and this thread is prevented to be used to process any other request during that period. As a result the thread gets stuck until the lengthy request is complete. If all the threads are stuck doing lengthy tasks the subsequent additional requests starts to queue up and when the queue fill up ASP.NET starts spitting 503 “Server Unavailable” errors.

ASP.NET provides a neater solution to this problem via Asynchrounous web handlers that implements the IHtttpAsyncHandler. The interface suggests to implement two additional methods BeginProcessRequest method and  EndProcessRequest. The idea is to spawn  an additional thread by hand in response to BeginProcessRequest, then perform the lengthy task in this additional thread and notify when the task is complete so the worker thread can return a response to the user.  We will look at Asynchronous web handlers in a later post in more details. Lets continue to look at other techniques now.