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

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!


LVL 6
PoeticAudioAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

AGBrownCommented:
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?

Andy
0
AGBrownCommented:
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.
0
PoeticAudioAuthor Commented:
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
0
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

AGBrownCommented:
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.

Andy
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
AGBrownCommented:
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.
0
PoeticAudioAuthor Commented:
Cool.

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.
0
AGBrownCommented:
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.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.