Advanced Asychronous Web Services

Article Description

This application shows how to use asynchronous Web services in your application and how you can use the callback method to make your application. I made this application to calculate the speedup for the case when you want to run long process in different machines versus a single machine.

This machine displays which job is running which task and the latest task displays in red.

My Approach

I used .NET/C#/SOAP and Web services techniques to implement this. The neat part of using Asynchronous .NET Web services is that they call the callback function when the function at the other machine is completed; this solves lots of complications from the project, especially when we need to dispatch 400 jobs. Then, I just check about which machine calls the callback—that means that machine is free now—so I send the next task dispatch to that machine.

Asynchronous Web Service

When you create any Web method, it creates an asynchronous method for you also; it has the “Begin” keyword before the Web method name.

For example, I have the SortMachine1 Web method, so I call it like this.

BeginSortMachine1(parameter,CallBackFunction,0);

This is a callback function. When an asynchronous Web service completes, this function gets called.

public void OnCBMachine1(IAsyncResult ar)
{
try
{
if (false == bIsBtn400Clicked)
{
   mylist1[0]           = st.EndSortMachine1(ar);
   bMachineDone[0]      = true;
   eTime[0]             = System.DateTime.Now;
   timeDiff[0]          = eTime[0].Subtract(sTime[0]);
   lblMachine1Time.Text = timeDiff[0].TotalMilliseconds.ToString();
   lblMsg1.Text         = "Finished Machine 1 Job.";

   if ( bMachineDone[1] == true &&
      bMachineDone[2]   == true &&
      bMachineDone[3]   == true )
   {
      timeDiff[4]       = eTime[0].Subtract(sTime[0]);
      lblTimeTaken.Text = timeDiff[4].TotalMilliseconds.ToString();
      double dTime      = timeDiff[4].TotalMilliseconds /
                          Int32.Parse(datasize4.Text);
      avg4.Text         = dTime.ToString();
      task4.Text        = (timeDiff[4].TotalMilliseconds /
                          4).ToString();
      lblInfo.Text      = "Job Completed";
   }
}
else
{
   mylist400[nCounterMachine1] = st.EndSortMachine1(ar);
   bMachineDone[0]       = true;
   eTime[0]              = System.DateTime.Now;
   timeDiff[0]           = eTime[0].Subtract(sTime[0]);
   TotalTimeFor400Tasks += timeDiff[0].TotalMilliseconds;
   lblMachine1Time.Text  = timeDiff[0].TotalMilliseconds.ToString();
   lblMsg1.Text          = "Finished Machine 1 Job # " +
                           (nCounterMachine1+1).ToString();

   lblTimeTaken.Text = TotalTimeFor400Tasks.ToString();
   double dTime = TotalTimeFor400Tasks /
                  Int32.Parse(datasize400.Text);
   avg400.Text  = dTime.ToString();
   task400.Text = (TotalTimeFor400Tasks /
                  nCurrentJobIndex).ToString();
   if ( nCurrentJobIndex == 400)
   {
      lblInfo.Text = "Job Completed";
      dTime = TotalTimeFor400Tasks / Int32.Parse(datasize400.Text);
      avg400.Text = dTime.ToString();
      task400.Text = (TotalTimeFor400Tasks /
                     nCurrentJobIndex).ToString();
   }
   else
      ServiceJobs();
}
}
catch(Exception ex)
{
   lblInfo.Text = ex.Message.ToString();
}
}

Part of the Projects

I created the project in two parts:

  • Server: This is an XML Web service, which has four Web methods that sort the data using a (O)n2 algorithm. Creating an XML Web service is a very easy task in .NET. The tricky part is that I want to use these methods asynchronously. When you create a Web service in .NET, it creates that method both asynchronously and synchronously. All you need to add is a Begin keyword, if you want to use that method as asynchronous. Also, you need to assign a callback function that is called by the Web method when the Web method is completed.

    I create XML Web services that are running on four different machines; these Web services contain the function for the sorting of data (On2) algorithm. This Web service is called DataProcess and has four functions.

  • Client Application (Windows-Based Application): This is the second application I made. This is simple Windows-based application in C# .NET. and I added the Web reference for the services I put on the different computer on my office LAN. Searching for all the available Web services is very easy in .NET.

    Screen shot of an application.

    Clicking the Add Reference button will open this dialog.

If you click on the local machine, it searches your machine and gives you a list of Web services available on your computer.

It’s a Windows-based application. It’s a simple application that has three options:

  • Single thread: This means the application runs on same machine as a full task and estimates the time.
  • 4 Tasks: Because we have four machines, we create four tasks, assign the job to each machine, and start the timer. When all the jobs are finished, count that time. Subtract this time from the start time; that is total time taken by this method.
  • 400 Tasks: This is tricky part. I solve this part in following order.
  • Create 400 tasks.

    1. Start the timer.
    2. Send first four tasks to four machines, and keep the counter of the current job.
    3. We call all jobs asynchronously, so as soon as I get a callback function from a machine, I send another job on line and increment the counter.
    4. Keep doing this until the counter reaches 400 (this means all jobs are dispatched).
    5. Now, wait for the last job to complete. As soon as you get that callback, mark that time.
    6. Take the difference of this time from the start time. That is your total time taken from this method.

Analysis

Single machine Test Analysis

All time are in milliseconds.

Single Process 4 Tasks 400 Tasks
6232.6224 5868.4384 11796.9632

Single machine test analysis

When I first read the problem, I assumed that the performance for 400 tasks will be better than for four tasks, even for a single machine, But, the results are completely the opposite. The reason: When I run 400 tasks on the same machine, its takes up the whole CPU time, CPU usage is 100%, which dramatically slows down the whole system performance. This project is designed to run on four different machines, so you will not achieve the same result by running on the same machine.

Multiple machine test analysis

Single Process 4 Tasks 400 Tasks
7232.6224 6987.5476 2214.7874

In this case, we get a much better result for 400 tasks, but for four tasks, it’s not much of an improvement. I think there are two reasons for that:

  1. For four tasks, we create a connection object for each machine so that we can call Whe web service. This introduces a slowdown for the first call.
  2. Each slave machine called the function only one time, so nothing is in the cache at this point.

The reason for getting a better result in the case of 400 tasks is as follows: We create an connection object only once and then keep calling the Web service again and again. This enhances the performance.

Tt = Total time to execute job one as single program.
Tp = Time of that part of the job. That can be broken down into independent tasks.
Speed Up = S(k) = Tt / Tk = 7232.6224 / 2214.7874 = 3.265

Theoretical speedup

Here K = 4. Let’s assume that ß = 1. This is an ideal case, when everything is distributed.

Then, S(k) = 4.

If ß = .96
S(k) = 1/ (.04+ .24) = 1/ .28 = 3.57

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read