Search code examples
c#multithreadingweb-services.net-2.0

Threading calls to web service in a web service - (.net 2.0)


Got a question regarding best practices for doing parallel web service calls, in a web service. This is for a back up plan in the case another potion of the project is unable to be delivered on time. I'd rather have something that works, even if it's throw-away, so the end user isn't interrupted.

Our portal will get a message, split that message into 2 messages, and then do 2 calls to our broker. These need to be on separate threads to lower the timeout.

One solution is to do something similar to (pseudo code): *Update: Not as efficient as was thought, executes fast but no as fast as calling is asynchronously through a delegate.

XmlNode DNode = GetaGetDemoNodeSomehow();
XmlNode ENode = GetAGetElNodeSomehow();
XmlNode elResponse;
XmlNode demResponse;
Thread dThread = new Thread(delegate
{
    //Web Service Call
    GetDemographics d = new GetDemographics();
    demResponse = d.HIALRequest(DNode);
});
Thread eThread = new Thread(delegate
{
    //Web Service Call
    GetEligibility ge = new GetEligibility();
    elResponse = ge.HIALRequest(ENode);
}); 
dThread.Start();
eThread.Start();
dThread.Join();
eThread.Join();
//combine the resulting XML and return it.
//Maybe throw a bit of logging in to make architecture happy

Another option we thought of is to create a worker class, and pass it the service information and have it execute. This would allow us to have a bit more control over what is going on, but could add additional overhead.

Another option brought up would be 2 asynchronous calls and manage the returns through a flag: Update: *This is not as efficient as the updated way I tried. This is 25% slower (running optimized) as the one I have below.

        personRevisedService.GetDemoCompleted += new GetDemoCompletedEventHandler(GetDemo_Completed);                      
        personRevisedService.GetDemoAsync(SomeXML);

The portal service will be called about 50,000 times a day.

I don't want to gold plate this sucker.

I'm looking for something light weight. The services that are being called on the broker do have time out limits set, and are already heavily logged and audited, so I'm not worried on that part.

This is .NET 2.0 , and as much as I would love to upgrade I can't right now. So please leave all the goodies of > 2.0 out please.

Update

I decided to call them using a delegate. Because this is a test, I'm calling the same service twice, as the other service is not yet built. It executed on average 20-30% faster than using [WebServiceName]Async(...),

public delegate XmlElement HServiceDelegate(XmlElement xml);


HServiceDelegate del1 = new HServiceDelegate(ws1.HGetDemographics);
HServiceDelegate del2 = new HServiceDelegate(ws2.GetDemographics);

IAsyncResult async1 = del1.BeginInvoke(x1.DocumentElement, callback1, null);
IAsyncResult async2 = del2.BeginInvoke(x2.DocumentElement, callback2, null);

//Not sure if this is the most efficient
while (!async1.IsCompleted && !async2.IsCompleted)
{
    System.Threading.Thread.Sleep(5);
}



void callback1(IAsyncResult result)
{
    AsyncResult r = (System.Runtime.Remoting.Messaging.AsyncResult)result;
    HServiceDelegate caller = (HServiceDelegate)r.AsyncDelegate;
    r1 = caller.EndInvoke(result);
}

Solution

  • Your approach is very inefficient, and may very well cause more harm than good. You'll be tying up a worker thread until both calls are complete, and you'll be producing many full threads, for no good reason.

    Look into making your service asynchronous, and using the Begin/End* methods of your web references.