How To Check Long Server-Side Process Progress In Real Time

Problem Statement

Very often, we receive requirements from the client to show the real-time progress of a long running process at the web server such that the end user gets notified on  real-time basis.

Today, I will tell you a way to monitor the long server-side progress (like, a long running process, file generation etc.) in real time in your web application. The whole demonstration will be covered through ASP.NET C# but you can also implement the same sort of code in other languages as well.

To implement this in ASP.NET, we need jQuery library. In my case, the project structure looks like below.

ASP.NET

In brief about the components available in the above project:

  1. Icons Contains plain and simple image/ico files to make the visual representation better.
  2. Models Contains two classes and one enum.

    ASP.NET
    Progress class contains the list of progress steps. The ‘ProgressSteps’ are basically the various steps inside the long running process. The ‘ProgressStatus’ is nothing but the different flags that are used to mark the type of the step completed.

  1. aspx is our landing page which contains one plain and simple button ;after clicking on that it redirects to the Home.aspx. In the page load of Home.aspx, we have the long running process.

Design plan

ASP.NET

Working Principle

  • The plan is to hold each step of the process in a Progress model object and keep it stored in session. So, just create a session property inside aspx.cs.
    1. private const string sessionKey = "progress";  
    2.         public Progress Progress  
    3.         {  
    4.             get  
    5.             {  
    6.                 if (Session[sessionKey] == null)  
    7.                     Session.Add(sessionKey, new Progress());  
    8.                 return Session[sessionKey] as Progress;  
    9.             }  
    10.             set  
    11.             {  
    12.                 Session[sessionKey] = value;  
    13.             }  
    14.         }  

  • Then write down your long running method in Home.aspx. In this demo, to have a feel of a long running process, I have used Thread.Sleep to make a delay of 2 seconds for each step. For each step, I have stored the step description in the session object.
    1. public void StartDownloadExecute()  
    2.         {  
    3.             for (int i = 0; i < 5; i++)  
    4.             {  
    5.                 //if(i==7)  
    6.                 //    Progress.Add(new ProgressStep(string.Format("Step # {0}", i), ProgressStatus.Error));  
    7.                 //else  
    8.                 Progress.Add(new ProgressStep(string.Format("Step # {0}", i), ProgressStatus.InProgress));  
    9.                 Thread.Sleep(2000);  
    10.             }              
    11.             // ------Write further code to mark the process completed  
    12.         }  

  • The heart of this code is a delegate. It resides in aspx.cs and used to execute the long running process asynchronously through a managed thread.
    1. public delegate void Run();  

  • In the page load, execute the long running process through the delegate and in the callback of the delegate, mark completion and pass a special flag to notify the monitoring logic as well.
    1. protected void Page_Load(object sender, EventArgs e)  
    2.         {  
    3.             StartDownload();  
    4.         }          
    5.   
    6.         public void StartDownload()  
    7.         {  
    8.             Progress = null;  
    9.             Progress.Add(new ProgressStep("Download Started", ProgressStatus.InProgress));  
    10.   
    11.             Run run = new Run(StartDownloadExecute);  
    12.   
    13.             IAsyncResult res = run.BeginInvoke((IAsyncResult ar) =>  
    14.             {  
    15.                 Progress.Add(new ProgressStep("Download Completed", ProgressStatus.Completed, "000ABORT_CHECK000"));  
    16.             }, null);  
    17.         }  

  • Now, the final step is to create a static asp.net webmethod inside aspx.cs. This webmethod, whenever called, will return the data stored in our session storage.
    1. [WebMethod(EnableSession = true)]  
    2.         public static string CheckDownload()  
    3.         {  
    4.             return HttpContext.Current.Session[sessionKey] == null ? string.Empty  
    5.                 : ((Progress)HttpContext.Current.Session[sessionKey]).ToString();  
    6.         }  

  • Once the coding for aspx.cs is done, it’s the time to write up the monitoring logic in Home.aspx using plain jquery. The monitoring logic is just a simple ajax call which keeps on calling the above mentioned webmethod in every 2 seconds and writes up the returned data on a label.

    The inbuilt javaScript interval listener has been used for our purpose. It stops checking further whenever the special flag (‘000ABORT_CHECK000’) is received.
    1. <script type="text/javascript">  
    2.         var _lblMsg = '<%=lblMsg.ClientID%>';  
    3.         $(document).ready(function () {  
    4.             var downloadComplete = false;  
    5.             var intervalListener = window.setInterval(function () {  
    6.                 if (!downloadComplete)  
    7.                     CallCheckDownload();  
    8.             }, 2000);  
    9.   
    10.             function CallCheckDownload() {  
    11.                 $.ajax({  
    12.                     type: "POST",  
    13.                     url: "Home.aspx/CheckDownload",  
    14.                     contentType: "application/json; charset=utf-8",  
    15.                     dataType: "json",  
    16.                     success: function (r) {  
    17.                         updateStatus('completed', r.d);  
    18.                         if (r.d.indexOf('000ABORT_CHECK000') > -1) {  
    19.                             downloadComplete = true;                         
    20.                             // Write further code per your requirement  
    21.                         };  
    22.                     },  
    23.                     error: function (r) {  
    24.                         console.log('Check error : ' + r.responseText);  
    25.                     },  
    26.                     failure: function (r) {  
    27.                         console.log('Check failure : ' + r.responseText);  
    28.                     }  
    29.                 });  
    30.                 if (downloadComplete)  
    31.                     window.clearInterval(intervalListener);  
    32.             };  
    33.             function updateStatus(status, msg) {  
    34.                 document.getElementById(_lblMsg).innerHTML = msg;  
    35.             };  
    36.         });  
    37.     </script>  

  • Thus, the output becomes as given below.

    ASP.NET

Conclusion

This is the easiest way to track server side long running processes using very simple jQuery and C# code and the beauty of delegate. I hope you enjoyed the article. Keep on learning 😊