Ask a Question related to ASP.NET Web Services, Design and Development.
-
Jonathan Trevor #1
Blocking problem/bug with enableSession=true and asynchronous web service calls?
Hi,
I've found what appears to be a bug with ASP.NET web service method
invocation - making it impossible to invoke and get the result of a
synchronous web call after an asynchronous call has been made if both are
using sessions.
Heres an example for two calls in the web service, the first is expected to
be executed asynchronously by the client and the second to get the progress
of the first while it is executing:
[SoapRpcMethod(RequestNamespace="",ResponseNamespac e="")]
[WebMethod(EnableSession = true, Description="")]
public MyResult DoLongTask(string progressHandle)
{
try
{
Thread.Sleep(7000);
return new MyResult();
} catch (Exception ex) { return null; }
}
static int count=0;
[SoapRpcMethod( RequestNamespace="",ResponseNamespace="")]
[WebMethod (EnableSession = true, Description="")]
public ProgressEvent GetProgress(string progressHandle)
{
try
{
Debug.WriteLine(DateTime.Now.ToLongTimeString()+ " Trying to get
progress for "+progressHandle);
ProgressEvent pe = new ProgressEvent(count+=10);
if (count==100) count=0;
return pe;
} catch (Exception ex) { return null;}
}
I stripped the calls down to almost nothing, removing the progress updating
and sharing to try and isolate the cause of a strange problem in the client:
e.g.
MyService ap = new MyService();
ap.CookieContainer = new CookieContainer();
ap.Login("blah");
string handle = Guid.NewGuid().ToString("N");
System.Diagnostics.Debug.WriteLine(DateTime.Now.To LongTimeString()+" FORM1:
About to do long task");
ap.BeginDoLongTask(handle);
System.Diagnostics.Debug.WriteLine(DateTime.Now.To LongTimeString()+" FORM1:
Back from do long task begin call");
ProgressEvent e = null;
bool done = false;
while (!done)
{
try
{
System.Diagnostics.Debug.WriteLine(DateTime.Now.To LongTimeString()+"
FORM1: Getting progress");
e = ap.GetProgress(handle);
System.Diagnostics.Debug.WriteLine(DateTime.Now.To LongTimeString()+"
FORM1: Got progress");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
if (e!=null) {
Debug.WriteLine(e.percentComplete);
if (e.percentComplete==100) done = true;
}
Application.DoEvents();
}
}
What you'd expect is that the async call will return immediately and then
for the GetProgress calls to quickly count to 100. That isn't what happens.
The BeginDoLongTask call does complete immediately but there is a 7 second
gap between the time printed by "FORM1: About to do long task" and the
return value from that - which should be almost instant. That gap is EXACTLY
the same as the sleep and you can play with that figure to see it's the
same. Further, the very first writeline in the GetProgress call on the
server ("Trying to get progress for ") DOES NOT EXECUTE until the
*asynchronous* call on the server has finished. Once the first "blocked"
GetProgress call succeeds the remaining GetProgress calls work as expected.
This is all really messed up.
However, the "cure" (or at least workaround) after two confused days is to
take "enableSession=true" out of either of the GetProgress or DoLongTask
methods (or make the DoLongTask OneWay=true). Then you get the expected
behavior: the GetProgress calls quickly count to 100 regardless of what is
happening (what sleep) in the DoLongTask call.
So whats going on here? Am I doing something really wrong? Why should the
"enableSession" flag cause this incorrect behaviour? And how can I actually
use the session in both methods?
Jonathan
Jonathan Trevor Guest
-
Web service calls asynchronous vs synchronous
The best solution is to design you architecture using the observer pattern(GOF) K,Browne Developer -
handling exceptions in asynchronous web service calls
I have a win forms application that calls a web service asynchronously. Occassionally, the web service call with raise an exception. Unfortunately,... -
Asynchronous web service calls
Hi I am trying to do some tests using asynchronous web service calls and have hit a problem. I have reduced the problem to the minimum so... -
Asynchronous web service calls, will you still have timeouts
If I am calling web services asynchronously, will I still have to be concerned with the request timing out? If IIS starts a process (calling a web... -
how to make asynchronous call to web service when its OneWay property is set to true.
I have web service with the following signature public void Update(XmlElement objElement) { // //call another C# library that update the... -
Sami Vaaraniemi #2
Re: Blocking problem/bug with enableSession=true and asynchronous web service calls?
There are a number of things that affect the level of concurrency of Web
service requests.
First, the calls are serialized in the *client* if you make more than two
calls from one AppDomain to one Web service. You can work around this by
changing the ServicePointManager.DefaultConnectionLimit property in the
client. But note if you do this then you are effectively violating the HTTP
1.1 protocol that says that you can make at most two simultaneous requests
from one client to one web server.
Second, two (or more) calls from one client to one Web service will be
processed by one thread in the server (and thus serialized) if the web
service method uses a session. This is the way ASP.NET runtime works and is
not exactly a bug IMO. It is documented e.g., KB article 820913
([url]http://support.microsoft.com/default.aspx?kbid=820913[/url]).
In an application I worked on the requirements dictated that I needed
session state, and I also had to be able to send multiple requests from one
client to the Web service to be processed concurrently. I worked around the
concurrency issues by not using the ASP.NET session state but implementing a
small COM+ component for storing the session state.
Regards,
Sami
[url]www.capehill.net[/url]
"Jonathan Trevor" <trevor@fxpal.com> wrote in message
news:uwVlLHR8DHA.1632@TK2MSFTNGP12.phx.gbl...to> Hi,
>
> I've found what appears to be a bug with ASP.NET web service method
> invocation - making it impossible to invoke and get the result of a
> synchronous web call after an asynchronous call has been made if both are
> using sessions.
>
> Heres an example for two calls in the web service, the first is expectedprogress> be executed asynchronously by the client and the second to get theupdating> of the first while it is executing:
>
> [SoapRpcMethod(RequestNamespace="",ResponseNamespac e="")]
> [WebMethod(EnableSession = true, Description="")]
> public MyResult DoLongTask(string progressHandle)
> {
> try
> {
> Thread.Sleep(7000);
> return new MyResult();
> } catch (Exception ex) { return null; }
> }
>
> static int count=0;
> [SoapRpcMethod( RequestNamespace="",ResponseNamespace="")]
> [WebMethod (EnableSession = true, Description="")]
> public ProgressEvent GetProgress(string progressHandle)
> {
> try
> {
> Debug.WriteLine(DateTime.Now.ToLongTimeString()+ " Trying to get
> progress for "+progressHandle);
> ProgressEvent pe = new ProgressEvent(count+=10);
> if (count==100) count=0;
> return pe;
> } catch (Exception ex) { return null;}
> }
>
> I stripped the calls down to almost nothing, removing the progressclient:> and sharing to try and isolate the cause of a strange problem in theFORM1:>
> e.g.
> MyService ap = new MyService();
> ap.CookieContainer = new CookieContainer();
> ap.Login("blah");
> string handle = Guid.NewGuid().ToString("N");
> System.Diagnostics.Debug.WriteLine(DateTime.Now.To LongTimeString()+"FORM1:> About to do long task");
> ap.BeginDoLongTask(handle);
> System.Diagnostics.Debug.WriteLine(DateTime.Now.To LongTimeString()+"happens.> Back from do long task begin call");
> ProgressEvent e = null;
> bool done = false;
> while (!done)
> {
> try
> {
> System.Diagnostics.Debug.WriteLine(DateTime.Now.To LongTimeString()+"
> FORM1: Getting progress");
> e = ap.GetProgress(handle);
> System.Diagnostics.Debug.WriteLine(DateTime.Now.To LongTimeString()+"
> FORM1: Got progress");
> }
> catch (Exception ex)
> {
> System.Diagnostics.Debug.WriteLine(ex.Message);
> }
> if (e!=null) {
> Debug.WriteLine(e.percentComplete);
> if (e.percentComplete==100) done = true;
> }
> Application.DoEvents();
> }
> }
>
> What you'd expect is that the async call will return immediately and then
> for the GetProgress calls to quickly count to 100. That isn't whatEXACTLY>
> The BeginDoLongTask call does complete immediately but there is a 7 second
> gap between the time printed by "FORM1: About to do long task" and the
> return value from that - which should be almost instant. That gap isexpected.> the same as the sleep and you can play with that figure to see it's the
> same. Further, the very first writeline in the GetProgress call on the
> server ("Trying to get progress for ") DOES NOT EXECUTE until the
> *asynchronous* call on the server has finished. Once the first "blocked"
> GetProgress call succeeds the remaining GetProgress calls work asactually>
> This is all really messed up.
>
> However, the "cure" (or at least workaround) after two confused days is to
> take "enableSession=true" out of either of the GetProgress or DoLongTask
> methods (or make the DoLongTask OneWay=true). Then you get the expected
> behavior: the GetProgress calls quickly count to 100 regardless of what is
> happening (what sleep) in the DoLongTask call.
>
> So whats going on here? Am I doing something really wrong? Why should the
> "enableSession" flag cause this incorrect behaviour? And how can I> use the session in both methods?
>
> Jonathan
>
>
Sami Vaaraniemi Guest



Reply With Quote

