Click here to Skip to main content
16,012,223 members
Articles / Web Development / ASP.NET

Asynchronous Access to Long Running Web Service Tasks

Rate me:
Please Sign up or sign in to vote.
2.67/5 (2 votes)
27 Apr 2009CPOL3 min read 28.6K   194   24   1
Asynchronous access to long running Web Service tasks

Introduction 

Quite often we have to deal with slow and lengthy Web Services tasks and consuming such Web Services can be equally frustrating. One solution to overcome this problem is to access the Web Service in an asynchronous manner while running the slow and lengthy Web Service task itself asynchronously. The beauty of the solution is that it is non blocking asynchronous call and the UI remains unaffected. 

Using this method also helps you maintain and manage state in your Web Services.

Again this is probably just one possibility to many solutions in dealing with this kind of an issue.

Background  

I came across this issue while surfing the ASP.NET forum. I found it to be an extremely interesting problem simply because the solution could be as convoluted as this.

When the client that is consuming the slow and lengthy service initiates the Web Service call, the webmethod generates and returns a GUID. Using this as a key we create an entry in the HTTPRuntime Cache and spawn a background thread that runs the slow and lengthy task and when complete, will update the HttpRuntime Cache entry with the result. 

The client periodically polls the Web Service to check if the slow and lengthy task has completed.  

Using the Code    

The download zip includes a Web app client that incorporates an AJAX based polling system and a Web Service that runs the task in a background thread. 

Client Code  

The client initiates the web request by calling the startCalculate web method and storing the id it receives in a session object called key:

C#
 protected void Button1_Click(object sender, EventArgs e)
 {
       Session["key"] = sv.startCalculate();
       Lab_Result.Text = "Retrieving the result for ID " + Session["key"].ToString() 
       + " ...";   
 } 

The client uses the AJAX timer control's Tick event to do the polling. It calls the  retrieveValue(string ID) by passing the ID stored in the session object called key.  If returned value is "Waiting" or contains "Retrieving" I continue polling for the result. Once the result is returned, it will no longer poll reducing on unnecessary calls to the Web Service.

C#
 protected void Timer1_Tick(object sender, EventArgs e)
 {
        if (Session["key"] != null)
        {
              TmpVar = Lab_Result.Text;

              if ((TmpVar == "Waiting!") || (TmpVar.Contains("Retrieving")) || 
              (TmpVar == null))
              {
                  TmpVar = sv.retrieveValue(Session["key"].ToString());
              }

              Lab_Result.Text = TmpVar;
        }
 }  

Web Service Code

The following Webservice SlowServiceInMemory exposes two web methods startCalculate()  and retrieveValue(string ID)

The startCalculate() method generates an ID, which it returns to the consuming client. It creates a HTTPRuntime Cache entry using the ID and calls the calculate(string key) method that in turn spawns a background thread to complete the slow and lengthy task.

C#
 [WebMethod]
        public string startCalculate()
        {
            string key = Guid.NewGuid().ToString();
            insertCacheObject(key, "Waiting!");
            calculate(key);
            return key;
        }   

The insertCacheObject method makes the Cache entry using the string key as an identifier.

C#
 private void insertCacheObject(string key, string ver)
 {
            HttpRuntime.Cache.Insert(
               key
               , (object)ver
               , null
               , DateTime.Now.AddSeconds(15)
               , Cache.NoSlidingExpiration);
 }

The retrieveValue(string key) web method retrieves the result that is stored in the HttpRuntime.Cache entry using the key.

C#
[WebMethod]
        public string retrieveValue(string key)
        {
            string tmp = "Waiting!";
            try
            {
                tmp = HttpRuntime.Cache.Get(key).ToString();
            }
            catch (Exception ex)
            {
                tmp = "Error " + ex.Message;
            }
            return tmp;
        }

The calculate(string key) method spawns a background thread to perform the slow and lengthy task. It then stores the result in the Cache entry.  You can further experiment  by changing the Thread.Sleep value to a smaller or larger number.

C#
private void calculate(string key)
{
    Thread th = new Thread(
        delegate()
        {
            Thread.Sleep(10000);
            string Tmp = "Result for long running class!";
            insertCacheObject(key, Tmp);
        });
    th.IsBackground = true;
    th.Start();
}

Points of Interest 

You could extend this implementation to persist the result to a database or a flat file instead of the cache.    

History  

  • 27th April, 2009: Initial post

I would like to implement asynchronous calls to the Web Service using the IAsynchResult pattern. The IAsynchResult pattern supports a non blocking callback implementation for asynchronous calls to the Web Service. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Infosolvex Solutions Inc
Australia Australia
Ritesh is an IT consultant with over ten years of experience in the IT industry varying from consultation, architecture, design, development to technical management. He has a strong background in solutions and applications architecture with a focus on Microsoft’s .Net platform. His area of expertise spans design and implementation of client/server, database and web-based systems. He has worked with C#, ASP.NET 1.1 and 2.0, ADO.NET, Web Services and SQL technology on several enterprise class projects.




Freedom is not worth having if it does not include the freedom to make mistakes.
Mahatma Gandhi

Comments and Discussions

 
GeneralMy vote of 2 Pin
Fran Moreno6-May-09 7:40
professionalFran Moreno6-May-09 7:40 
it�s not a good way to resolve long requests.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.