Building and Using Asynchronous Web Services


In this article I will show how to build and use asynchronous Web services in your application and how you can use the callback method to make your application work in asynchronous state. I made this application to calculate the speedup for the case when you want to run long process in different machines versus single machine.

This application shows what jobs are running, what jobs have been finished and some other data related to the jobs such as time and data size.



My Approach

I used .NET/ C# / SOAP and web services technique to implement this. The neat part of using asynchronous .NET web services is that they call the callback function when the function at other machine is completed, which solves lots of complicacy from the project. Specially when we need to dispatch 400 jobs then I just check about which machine calls the callback, 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 its create a asynchronous method also for you, which have the Begin keyword before the web method name.

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

BeginSortMachine1(parameter,CallBackFunction,0);

This is a call back function, when an asynchronous web service completed this function get 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();
}
}

The attached project has two parts - the Web service and the client application.

The Web Service

This is an XML web service, which has four web methods, that sorts the data using (O)n2 algorithm. Creating and XML web service is a very easy task in .NET. Tricky part is I want to use these method asynchronously. When you create a web service in .NET, it creates that method asynchronous and synchronous both. 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, which is called by web method, when web method is completed.

I create XML web services that are running on four different machine, and these web services contains the function for the sorting of data ( On2) algorithm. This web service is called DataProcess and four functions.



The Windows Forms Client Application

The client application is a Windows Forms applications written in C# .NET. and I added web reference for the services I put on the different computer on my office LAN. Searching for all the available web service is very easy in .NET.

The Add Web Reference dialog looks like following:



Click on add reference button will show up this dialog.



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

Its a windows based application. Its a simple application. It has 3 options.

Single thread: This means application runs on same machine as a full task and estimate the time.

4 Tasks: Since we have four machine, Create 4 tasks, and assign the job to each machine and start the timer and when all the jobs are finished then count that time. Subtract this time from start time, that is total time taken by this method.

400 Tasks: This is little 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 current job.
3. We call all jobs asynchronously, so as soon as I get a callback function from machine, I send another job on line and increment the counter.
4. Keep doing this until counter reaches 400 ( means all jobs are dispatched).
5. Now wait for last job to complete and as soon as you get that callback, mark that time.
6. Take a difference of this time from the start time, that is your total time taken from this method.

The test analysis report of single machine looks like following

All time are in milliseconds.





When I first read the problem, I assumed the performance for 400 tasks will be better than 4 task, even for single machine, But the results are completely opposite.

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 4 different machine, so you will not achieve the result by running on the same machine.

The test analysis report of multiple machines looks like following



In this case, we gets much better result for 400 tasks, but for 4 tasks its not much better 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 the web service, which introduce a slowdown for the first call.

2. Each salve machine called the function only one time, so nothing is n cache at this point.

Reason of getting better result in case of 400 tasks

1. We create an connection object only once and than keep calling the web service again and again, which enhances the performance.


Similar Articles