Blocking problem/bug with enableSession=true and asynchronous web service calls?

Ask a Question related to ASP.NET Web Services, Design and Development.

  1. #1

    Default 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

  2. Similar Questions and Discussions

    1. Web service calls asynchronous vs synchronous
      The best solution is to design you architecture using the observer pattern(GOF) K,Browne Developer
    2. 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,...
    3. 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...
    4. 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...
    5. 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...
  3. #2

    Default 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...
    > 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
    >
    >

    Sami Vaaraniemi Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139