Objective:
To display about progress message to user, when long running process goes on application
Introduction
This article presents Asp.net and C# code to create an Progress message about the background working in server. Web application is Client-Server architecture model. Web application always working in Request response model, this approach uses threading concept.
Approach
Whether we use Ajax or not, if it is a very long running process the browser may show a time-out error.
In case of ASP.NET AJAX if we use a script manager then we also have to define the time-out for the request which can be difficult in the scenario where we cannot predict how long a process will take to execute.
In this article we will discuss about this issue and how to use Ajax to handle long running process by using IAsyncResult and ICallbackEventHandler. Web applications are based on a client-server architecture, so when the client hits the server the server will reply. If a long process is running on the server, then we may need some mechanism to determine when the long process is over. The long process can also delay the execution of other processes. To handle this issue we will use IAsyncResult . Using this interface and delegates we will able to run asyncronous processes on server side and invoke one method on server side while continuing with other tasks; once first method is complete it will automatically call another server method so that we can update some parameters say VAR1 and VAR2. And using ICallback we can check for VAR1 and VAR2, as soon as we get updated values, we will change status of long running method on client.
Using IAsyncResult, delegates and AsyncCallback
Classes which support asynchronous operations implement the IAsyncResult interface. IAsyncResult objects are passed back to methods invoked by AsyncCallback when an asynchronous operation completes. Classes which supports AsyncCallback in their methods return object of type IAsyncResult, for example - FileStream.BeginRead and FileStream.EndRead (these methods support AsyncCallback hence the return type is IAsyncResult). The same is true for BeginGetRequestStream method of WebRequest.
If we look at the parameters in these methods there is an AsyncCallback parameter which is the method that gets called once Async method is over. In our code this method is CallBackMethod.
On server side, we have used a delegate and on the button click event the function named StartMethod() gets called. This function take cares of the LongRunningMethod registration for the delegate and invoking of LongRunningMethod. While invoking LongRunningMethod we register the AsyncCallback method i.e. CallBackMethod.
CallBackMethod method can also be used to do other operations which may be dependent on the LongRunningMethod.
We will create a simple LongRunningMethod as follows:
Here we store gloabalInt as Global value to show the status. Dictionary values to bind the values, it stored in session since after completing the method all the values destroyed.
/// <summary>
/// Your Long running method Name, you can specify parameter or just remove it and also remove in delegate
/// </summary>
/// <param name="name"></param>
private void LongRunningMethod(string optionalparameter)
{
//you can write your own code, below is sample code for long running
for (int i = 0; i <= 10; i++)
{
dctValues.Add(i.ToString(), i.ToString());
gloabalint = i;
Thread.Sleep(600 * 1);//This will run for 5 mins
}
//ddlContent.DataSource = dctValues;
//ddlContent.DataTextField = "key";
//ddlContent.DataBind();
Session["dictionary"] = dctValues;
//Response.Flush();
}
We will now declare a delegate for above function , parameters for the delegate and the method should be same, also the parameters are optional we can use either side or remove:
/// <summary>
/// Delegate for your long running method
/// </summary>
/// <param name="name"></param>
private delegate void LongRunDelegate(string optionalparameter);
Implementation of the Async process on server side, it uses the Namespace System.Runtime.Remoting.Messaging;
/// <summary>
/// This is your method which call
/// </summary>
/// <returns></returns>
private IAsyncResult StartMethod()
{
LongRunDelegate LongDelegate = new LongRunDelegate(LongRunningMethod);// Delegate will call LongRunningMethod
IAsyncResult ar = LongDelegate.BeginInvoke("CHECK", new AsyncCallback(CallBackMethod), null);
//”CHECK” will go as function parameter to LongRunningMethod
return ar; //Once LongRunningMethod get over CallBackMethod method will be invoked.
}
Create a Callback method for starting up the IAsyncResult
private void CallBackMethod(IAsyncResult ar)
{
AsyncResult Result = (AsyncResult)ar;
LongRunDelegate Long = (LongRunDelegate)Result.AsyncDelegate;
Long.EndInvoke(Result);
}
Long.BeginInvoke in StartMethod() will invoke LongRunningMethod method. While implenting this just check the parameters for BeginInvoke in .NET.
CallBackMethod gets called automatically after LongRunningMethod. CallBackMethod is used to end the invocation of the delegate.
On Start Process button click event we will call StartMethod function:
protected void StartProcess_Click(object sender, EventArgs e)
{
Response.Write("Long running process is started");
Session["result"] = null;
IAsyncResult res = StartMethod();
Session["result"] = res;
//Response.Redirect("RedirectedPage.aspx");
//You can redirect to some other page, prcoess will continue..
//since we are using session variable it will be available on another page also
//and you just need to check for process completion as we did in GetCallbackResult().
//On that page also we will have to use ICallback for priodic check.
}
Now we will implement Web Method for cheking status of the process.
Create a Web Method to receive the status message, it uses the namespace System.Web.Services;
[WebMethod]
public static string SaveContent(string content)
{
return gloabalint.ToString();
}
Client Side Code for Calling the Web Method & displaying the status message, Here I used JQuery for Scripting language and Aspx Page name is “StatusMessage.aspx”
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.min.js"></script>
<script type="text/javascript">
var x = null;
startProcessCheck();
function startProcessCheck() {
x = setInterval("GetprocessData()", 1000);
}
function GetprocessData() {
methodURL = "StatusMessage.aspx/SaveContent";
parameters = "{'content':'" + "1" + "'}";
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: methodURL,
data: parameters,
dataType: "json",
async: false,
success: function (data) {
$("#divmessage").html(data.d.toString());
},
error: function (result) {
}
});
if (parseInt($("#divmessage").html()) >= 10) {
clearInterval(x);
$("#BindDropdown").click();
}
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<div>
Start the process, it will automatically bind the dropdown
</div>
<br />
<asp:Button ID="btnStartProcess" runat="server" Text="Start Process" OnClick="StartProcess_Click" />
<br />
<br />
<br />
<br />
<div>Status Message: </div>
<div id="divmessage">
</div>
<br />
<br />
<br />
<br />
<div>Drop Down:</div>
<asp:DropDownList ID="ddlContent" runat="server" ></asp:DropDownList>
<asp:Button ID="BindDropdown" runat="server" Text="BindDropDown" OnClick="BindDropdown_click" style="display:none;" />
</div>
</form>
</body>
</html>
Technical Feasibility faced
· It is multi threading concept, so we have to ensure to not start more than one AsyncResult. It will avoid running of multiple instance of background processes
· We can’t able to use the response methods in AsyncResult, since it running asynchronously
References