I'm using the following code to call a web service that exists on up to 4
servers. I would expect that execution would block on the call to WaitAll
(I've got a 15 minute timeout coded) until there is a response from all the
web service calls. In my case the code exits WaitAll immediately and blocks
instead on the call to EndGetServerContents. Any ideas why I'm seeing this
behavior?
// get the contents of each server in the site to audit
int NumberOfServersInSite = SelectedSite.Servers.Count;
PrinterManagerWsProxy[] PrinterManagerWsProxies = new
PrinterManagerWsProxy[NumberOfServersInSite];
IAsyncResult[] AsyncResults = new
IAsyncResult[NumberOfServersInSite];
WaitHandle[] WaitHandles = new WaitHandle[NumberOfServersInSite];
ServerContents[] SiteConfigurations = new
ServerContents[NumberOfServersInSite];
for(int i=0; i<NumberOfServersInSite; i++)
{
PrinterManagerWsProxy proxy = new PrinterManagerWsProxy();
proxy.Url = "soap.tcp://" + SelectedSite.Servers[i].Name + ":" +
Properties.Settings.Default.PrinterManagerWsProxyPort + "/PrinterManagerWs";
PrinterManagerWsProxies[i] = proxy;
AsyncResults[i] = proxy.BeginGetServerContents(true, null, null);
WaitHandles[i] = AsyncResults[i].AsyncWaitHandle;
}
// wait for web service calls to return ... could do other work here if
there is any
WaitHandle.WaitAll(WaitHandles,
Properties.Settings.Default.PrinterManagerWsProxyTimeout, false);
// get web service call results
for (int i = 0; i < NumberOfServersInSite; i++)
{
if (AsyncResults[i].IsCompleted)
{
SiteConfigurations[i] =
PrinterManagerWsProxies[i].EndGetServerContents(AsyncResults[i]);
}
else
{
PrinterManagerWsProxies[i].Abort();
SiteConfigurations[i] = null;
MessageBox.Show(string.Format("Unable to get configuration information from
server {0}, results do not include this server.",
SelectedSite.Servers[i].Name), "Error!", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
Bill Knaus - 23 Oct 2006 18:44 GMT
Hi Don,
Thats because the WSE3.0 proxy created within Visual Studio is not
thread-safe and you must explicitly call the Endxx method in order to unblock.
In my local WSE3.0 doco - I discovered this at...
ms-help://MS.WSE30.1033/WSE3.0/html/510c53cb-4ded-47ab-9fbd-ab82ed229526.htm
The actual title of this document is "How to: Create a Proxy Class to
Communicate with a Web Service". At the bottom of the page there is the
following note...
"The WSE-enabled proxy class is not thread-safe. When the proxy class is
used to make multiple asynchronous calls to a Web service method, each call
must be completed using the EndXX method before another call may be made."
Now, because this is saying class, not sure if the class as a whole is not
thread safe or if your approach below of a new instance for each would work
around it. My assumption would be that there's something there where that
first call is holding onto the web service --- probably keeping the
communication channel open --- and not relinquishing it for the next call.
Hope this helps!
Bill Knaus
> I'm using the following code to call a web service that exists on up to 4
> servers. I would expect that execution would block on the call to WaitAll
[quoted text clipped - 46 lines]
> }
> }
Don - 30 Oct 2006 20:05 GMT
I don't think this is entirely the issue. I ended up opening a case
w/Microsoft and this is what I was told:
The bad news is that WSE doesn't support the asynchronous programming
pattern with BeginInvoke and EndInvoke.
The following bug talks about it and unfortunately its not going to be fixed.
http://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=123879&SiteID=211
The good news is that the alternative mentioned in the above article
SoapSender and SoapReceiver provides a framework to implement this.
Thanks for your input,
Don ...
> Hi Don,
>
[quoted text clipped - 72 lines]
> > }
> > }