Executing Long Running Operations - Part I
Introduction
In web applications you often end up in triggering a lengthy operation and
then getting the "time out" errors. This happens because the operation is taking
more time to complete than script timeout value of a page (which defaults to 3
minutes). One easy remedy to this problem might be to increase the script
timeout value of the page. However, what if your operation is taking too much of
time (say 20 minutes). Would you like your uses to wait for 20 minutes? Of
course not. There are more appropriate solutions to this situation and I am
going to discuss two of them in this two part article.
Long running tasks in a web service
The part-I of this article discusses about how to handle long running
operations in a web service. Here, we are assuming that you have a web
application that is acting as a client to this web service. By default when you
call a web method the caller waits till the time the web method returns. The
problem is - if your web method takes more time than the page script timeout
value then you will get timeout error. Hence, you want to trigger the web
service but do not want to wait till the web method completes. In other words
you simply want to call the web method and return immediately to the
caller. Let's see how this can be done with a simple example.
The web service
First, we will build a simple web service that will do a task for 5 minutes
(time greater than default script timeout value of 3 minutes).
- Create a new ASP.NET web service project in VS.NET
- Add following code to the Service1.asmx code behind file
[WebMethod]
public void StartProcessing()
{
DateTime dt1=DateTime.Now;
DateTime dt2=dt1.AddMinutes(5);
TimeSpan ts=new TimeSpan(0,0,0);
while(true)
{
dt1=DateTime.Now;
if(dt2.Subtract(dt1)==ts)
{
break;
}
}
}
}
Here, we created a web method called StartProcessing() that simply simulates
time delay of 5 minutes using a while loop.
You are now ready to consume it in a web application
The web application
- Add a new ASP.NET web application project to the above solution
- On the web form drag and drop a button control and a label
- Add "web reference" to the web service we created above
- Write following code in the Click event of the button
private void Button1_Click(object sender, System.EventArgs e)
{
localhost.Service1 s1=new localhost.Service1();
s1.StartProcessing();
Label1.Text="Processing completed!";
}
- Here, we are simply creating an instance of web service proxy and
calling the long running web method on that.
- If you run this web application it will wait for the web method to
finish and eventually timeout throwing an exception.
The Solution
The solution to solve above problem is to decorate your web method with a
special attribute called [SoapDocumentMethod(OneWay=true)]. Once you mark your
web method with this attribute the web service will return immediately with
response code of 202 after calling the method. This way your client feels that
the web method processing is over and becomes free to process further
operations. Here is how the web method looks like after decorating with
SoapDocumentMethod attribute:
[WebMethod]
[SoapDocumentMethod(OneWay=true)]
public void StartProcessing()
{
DateTime dt1=DateTime.Now;
DateTime dt2=dt1.AddMinutes(5);
TimeSpan ts=new TimeSpan(0,0,0);
while(true)
{
dt1=DateTime.Now;
if(dt2.Subtract(dt1)==ts)
{
break;
}
}
}
Note, how we have set the OneWay attribute of the SoapDocumentMethod
attribute to true.
By default, SOAP messages are in "document" style of formatting. If you are
using Remote Procedure Call (RPC) formatting then use [SoapRpcMethod(OneWay=true)]
instead of [SoapDocumentMethod(OneWay=true)].
The limitations
Though above technique works well in many situations it has some
disadvantages:
- It required that the web method must not return anything. This is
obvious because we are returning immediately without waiting for the web
method to finish.
- The use do not get any idea whether the method completed successfully or
there were some errors.
- The user do not receive any notification when the method ends.
- This works only for web service because the attribute we used is
available only for web methods.
Summary
In this part-I of the two part series, we saw how to execute long running web
methods from your web application. The SoapDocumentMethod attribute with OneWay
property set to true does the trick for us. In the next part we will see how to
use multithreading technique to do similar thing in a web form itself.