Multi-threading design decision... need some ideas... unfortunately it's rather urgent...

Posted on 2006-04-11
Medium Priority
Last Modified: 2010-04-16
Okay, I need help with making a good design decision. Here is my situation. I am willing to offer BIG points.

We have an application that contains a web service to get data from different attorneys. Here's how it works...

since any attorney can sign on to this service at any time we decided to set it up so the client end (non-attorney) makes a call to a single web service to get data.
This web service pulls in IP addresses from a table (IPs for the web services that sit on each attorney side), and then in turn calls another web service based on the IP it pulled.

here are the steps:
- Client calls GetData in WebService1
- WebService1 pulls in IPs (which are the urls for the web services on the attorney end) from a table
- WebService1 sets WebService2's IP to an attorney and has it grab the data
- WebService1 moves on to the next IP and does the same exact thing
- Repeat previous two steps, looping through each IP.

Here is the problem.
If there are 5 attorneys signed up, WebService1 gets to the third attorney and calls WebService2 and they are down, then we have a problem because the client will have to wait a long time while it times out on the third attorney and then moves on to the next... so I figured multi-threading would be a good idea here because I could have 5 (or however many) threads each pull in the data simultaniously and if one is down, then I can at least return the other 4 attorney's data quickly and prompt the user that such-and-such attorney was down and to try again later.

Here is the other problem.
The way this class has been designed makes this difficult for me. Right now it's designed so there is only 1 instance of WebService2 in WebService1 and WebService1 simply "steers" WebService2 to the right URL and when it's finished it "steers" WebService2  to the next URL and makes another call to get data. This makes multi-threading useless because I can't have 5 threads each trying to change the URL of WebService2 at the same time.

Should I bite the bullet and redo this class so it handles multiple WebService2's at the same time? The main problem here is that this is extremely urgent and i'm not sure how daunting it's going to be to re-design this class at this point. Great ideas are worth big points! =)

Thanks for reading all of that!

Question by:PoeticAudio
  • 5
  • 2
LVL 12

Expert Comment

ID: 16428582
In terms of design. If you do n things inside a web service, each of which could take some time, and none of which depend on each other then you are set up perfectly for improving your performance by doing each of them asynchronously.

So you're pretty much there already; in your case I would say you should definitely be doing asynchronous method calls from WebService1 to WebService2.

Questions I would have for you before going forward are:
-Does WebService1 contain a proxy for WebService2 that has been autogenerated using Visual Studio? (In which case, the WebService2 proxy already contains the stubs for the asynchronous methods in the autogenerated proxy for you to use.)
-Are you using .NET 2.0 or 1.1 (it gets a lot easier to do asynchronous things in .NET 2.0)
If you can answer these then we can start to work towards a solution.

If there is 1 instance of WebService2, it won't take much effort for you to replace that with a list object of WebService2 classes instead, so you don't need to worry about that.

You might also like to see if you can reduce the timeout on each of the WebService2 calls. Is that appropriate?

LVL 12

Expert Comment

ID: 16428623
PS The best design will involve setting up a class to handle the asynchronous calls to web service 2. I have examples in .NET 1.1 that I can show you, but as I say .NET 2.0 actually provides classes that will automatically do this for you.

You also need to be careful about how many webservice2 classes you will be calling concurrently as you can exhaust your thread pool if you have more than a few. Managing this is easy as you can set yourself up to fire off just 5 at a time, and as each one returns you can fire any waiting ones.

Author Comment

ID: 16428708
Thank you for the quick response and to answer your questions...

WebService1 does contain an autogenerated proxy for WebService2
I am using .NET 1.1 at the moment.

We only have 2 attorneys that are signed on for this, and there will probably never be more then 10 (and that's stretching it) in our scenerio.

Thanks Again
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

LVL 12

Accepted Solution

AGBrown earned 2000 total points
ID: 16428952
If you have 10, you _might_ be ok. I do exactly the same thing that you are trying to do, and I have limited it to 5 concurrent requests (I found that with the processing I was doing on each return, 5 gave me the best performance).

I would say you can take this in stages, and there is a very simple stage to start off with. There are a few ways to do asynchronous calls to webservices, but they don't change regardless of whether you are doing it from a client or another web service. The simplest, and if you are in a hurry then I would go with this for now, is to simply use the proxy; forget the wrapping and queue classes that I mentioned. You can just do as they suggest in MSDN (Chapter 10 — Improving Web Services Performance: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenetchapt10.asp). You want to look at the "Asynchronous Web Methods" and "Asynchronous Invocation" sections.

I think you would do something like:

private void CallServices(string[] ipAddresses)
      WebService[] services;
      IAsyncResult[] results;
      WaitHandle[] waitHandles;

      services = new WebService2[ipAddresses.Length];
      results = new IAsyncResult[ipAddresses.Length];
      waitHandles = new WaitHandle[ipAddresses.Length];
      for (int i = 0; i < ipAddresses.Length; i++)
            services[i] = new WebService2();
            services[i].Timeout = 10000; // milliseconds
            WebService2.Url = ipAddresses[i];
            results[i] = services[i].BeginAttorneyCall(data, arg, somethingelse);
            waitHandles[i] = results[i].AsyncWaitHandle;

      WaitHandle.WaitAll(waitHandles);  //choose between WaitAny and WaitAll depending on needs
      for (int i = 0; i < ipAddresses.Length; i++)
            string exampleReturn = services[i].EndAttorneyCall(results[i]);

Remember that by doing this you are opening yourself up to some design-debt, and that you should schedule some time in after this initial release to move to a more scalable method, so you can avoid the thread pool error (http://support.microsoft.com/default.aspx?scid=kb;en-us;815637).

Now, you might also decide later that you want to accept the client's request for data, and then return to them immediately letting them check back continuously for new results. In that case you would need to go with the wrapper approach I mentioned. You can set up your wrapper objects, pass them to a queue class which handles firing them and storing them, and store that somewhere (for example the Cache, ApplicationState etc.) to check the state of each wrapper object (stillGoing, Completed, Failed, NotAvailable) when the client periodically checks back.

LVL 12

Expert Comment

ID: 16429002
Oh, and I have mentioned but I should reinforce my comment that the wrapper and queue approach is a lot simpler in .NET 2.0, and given that you are running this in a web service, you could actually program just the web service in .NET 2.0 and leave the rest of the application in .NET 1.1. If you can't move to .NET 2.0, then I should also say that I didn't find it too painful to go with the proxy-wrapper approach. I would have found it very simple, and probably done it slightly better if I had had the new MSDN to read (http://msdn2.microsoft.com/en-us/library/hkasytyf(VS.80).aspx). You can basically mimic this pattern in .NET 1.1 without having the .NET 2.0 classes to use with very little effort.

Author Comment

ID: 16429861

The example you provided should give me a good starting point, along with that article. Keep an eye out for a few extra points!

Thanks again for all of the speedy responses.
LVL 12

Expert Comment

ID: 16429877
Don't worry about extra points, I'm just glad that that worked. I'll keep an eye out for future questions though, and if you do post any follow up questions you could always point to them from here to get my attention as I'll get the emails.

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article introduced a TextBox that supports transparent background.   Introduction TextBox is the most widely used control component in GUI design. Most GUI controls do not support transparent background and more or less do not have the…
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an anti-spam), the admin…
Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…
Suggested Courses
Course of the Month13 days, 18 hours left to enroll

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question