1

I saw a lot of examples about GeginGetContext but i have filling that all of them are waste time. Maybe i am wrong. Lets find out. Lets take for instance really good example from the Multi-threading with .Net HttpListener topic:

 public class HttpListenerCallbackState
{
    private readonly HttpListener _listener;
    private readonly AutoResetEvent _listenForNextRequest;

    public HttpListenerCallbackState(HttpListener listener)
    {
        if (listener == null) throw new ArgumentNullException("listener");
        _listener = listener;
        _listenForNextRequest = new AutoResetEvent(false);
    }

    public HttpListener Listener { get { return _listener; } }
    public AutoResetEvent ListenForNextRequest { get { return _listenForNextRequest; } }
}

public class HttpRequestHandler
{
    private int requestCounter = 0;
    private ManualResetEvent stopEvent = new ManualResetEvent(false);

    public void ListenAsynchronously(IEnumerable<string> prefixes)
    {
        HttpListener listener = new HttpListener();

        foreach (string s in prefixes)
        {
            listener.Prefixes.Add(s);
        }

        listener.Start();
        HttpListenerCallbackState state = new HttpListenerCallbackState(listener);
        ThreadPool.QueueUserWorkItem(Listen, state);
    }

    public void StopListening()
    {
        stopEvent.Set();
    }


    private void Listen(object state)
    {
        HttpListenerCallbackState callbackState = (HttpListenerCallbackState)state;

        while (callbackState.Listener.IsListening)
        {
            callbackState.Listener.BeginGetContext(new AsyncCallback(ListenerCallback), callbackState);
            int n = WaitHandle.WaitAny(new WaitHandle[] { callbackState.ListenForNextRequest, stopEvent});

            if (n == 1)
            {
                // stopEvent was signalled 
                callbackState.Listener.Stop();
                break;
            }
        }
    }

    private void ListenerCallback(IAsyncResult ar)
    {
        HttpListenerCallbackState callbackState = (HttpListenerCallbackState)ar.AsyncState;
        HttpListenerContext context = null;

        int requestNumber = Interlocked.Increment(ref requestCounter);

        try
        {
            context = callbackState.Listener.EndGetContext(ar);
        }
        catch (Exception ex)
        {
            return;
        }
        finally
        {
            callbackState.ListenForNextRequest.Set();
        }

        if (context == null) return;


        HttpListenerRequest request = context.Request;

        if (request.HasEntityBody)
        {
            using (System.IO.StreamReader sr = new System.IO.StreamReader(request.InputStream, request.ContentEncoding))
            {
                string requestData = sr.ReadToEnd();

                //Stuff I do with the request happens here  
            }
        }


        try
        {
            using (HttpListenerResponse response = context.Response)
            {
                //response stuff happens here  
                string responseString = "Ok";

                byte[] buffer = Encoding.UTF8.GetBytes(responseString);
                response.ContentLength64 = buffer.LongLength;
                response.OutputStream.Write(buffer, 0, buffer.Length);
                response.Close();
            }
        }
        catch (Exception e)
        {
        }
    }
}

Here we can see main part for this topic:

while (callbackState.Listener.IsListening)
        {
            callbackState.Listener.BeginGetContext(new AsyncCallback(ListenerCallback), callbackState);
            int n = WaitHandle.WaitAny(new WaitHandle[] { callbackState.ListenForNextRequest, stopEvent});
           ...
        }

I can saw this patterns in +- all examples. We are starting Getting Contex (Getting request = getting network stream with request) after that we are blocking current thread with Wait/WaitAny method, so thread witch is getting request is doing nothing until it will got full request after that it will getting new request. For example we are having WCF request with large object(which are deserialized in this request and are serialized in the same way on other side) so we will wait and WASTE TIME until we complete getting full steam with this request. I see that really it is Sync not Async way. Instead of this we can starting getting second request right after the starting getting first and not call Wait, not blocking thread. I think we will have much better performance in such way. What do you think? Why do all examples contains Wait?

Community
  • 1
  • 1
Brans Ds
  • 4,039
  • 35
  • 64
  • _"thread witch is getting request is doing nothing until it will got full request after that it will getting new request"_ - what makes you think so? – CodeCaster Sep 17 '13 at 11:16
  • I guess examples don't have anything else to do while waiting. Server applications by the way WASTE TIME alot (they usually only do something useful while processing a request) and `WaitAny` allows other threads or applications to do their thing while waiting. – C.Evenhuis Sep 17 '13 at 12:29
  • "what makes you think so?" Because we call Wait method - we are waiting until we EndGetContext (request from network stream) and only then Wait will be unblocked we we begin to get new request. – Brans Ds Sep 17 '13 at 13:00
  • C.Evenhuis isn't it will be better(faster) to process (BeginGetContext), for example 5 request simultaneously, not one? – Brans Ds Sep 17 '13 at 13:01
  • @BransDs before actually _processing_ the request, `callbackState.ListenForNextRequest` is set. So while the first request is processed, the listener is already accepting subsequent requests. Even if there was anything to optimize, what would the speed benefit be? 1%? At what cost? Unreadable code? – C.Evenhuis Sep 17 '13 at 13:12
  • No. Not 1% - much-much more. The time spent for on getting context is really significant. I investigated this during profiling of large real-word application (WCF listener service part)... sometimes because of this small request is waiting and UI response is slow... there are significant lags. – Brans Ds Sep 17 '13 at 13:23
  • that was the core reason of my question... profiling tells that it is botle-neck – Brans Ds Sep 17 '13 at 13:23

0 Answers0