Dimitris M
Dimitris M

Reputation: 79

Cannot access a disposed object. Object name: 'System.Net.HttpListener'

I am creating a windows service that listens for specific Http requests. I am running an httpListener in a separate task. When the service is stopped i close the listener instance. But it seems that the http listenerContext is waiting for an incoming request and as the listener get closed i get the following error

Cannot access a disposed object. Object name: 'System.Net.HttpListener'.

Even if i use some mechanism to inform StartListening() that listening is stopped, it will not run as the execution at the corresponding thread stuck at HttpListenerContext context = await _listener.GetContextAsync(); until a request arrives.

  public void StartListening() {
         _listener.Start();
         _logger.LogDebug("Http Listening started");

         Task.Run(async () => {
            while (true) {
               try {
                 if (isOpen == false) {
                 return 0;
                   }
                  HttpListenerContext context = await _listener.GetContextAsync();
                  HttpListenerRequest request = context.Request;

                  //processing of the requests url/////
                  var newUri = request.Url.AbsoluteUri;
                  _concurrentUrlQueue.Enqueue(newUri);
                  if (ConcurentUrlQueueChanged != null) ConcurentUrlQueueChanged(this, new EventArgs());
               }
               catch (Exception e) {
                  _logger.LogError("Error at get listening  context, Message: " + e.Message);
               }

            }
         });

      }    
      public void StopListening() {
          isOpen = false;
         _logger.LogDebug("Http Listening Stop");
         _listener.Close();

      }

Which is the appropriate way to close an http listener that is listening to get context. The code i use is the following. Thank you..

Upvotes: 2

Views: 8507

Answers (1)

Dimitris M
Dimitris M

Reputation: 79

I found a solution. As i understand the listener.GetContextAsync() is a blocking method, and the execution of my code will only continiou when a new context is detected. I can use the non blocking versions BeginGetContext() and EndGetContext(). When i want to stop execution i use a cancellation token.

   public void StartListening() {

         _listener.Start();
         _logger.LogDebug("Http Listening started");

         Task.Run(() => {
            while(true) {

               if(_cancellationToken.IsCancellationRequested) return ;

               try {
                  NonblockingListener();
               }
               catch (Exception e) {
                  _logger.LogError("Error With the listening Proccess, Message : "+e.Message);
               }

            }
         },_cancellationToken);
      }


      public void StopListening() {

         _cancellationTokenSource.Cancel();
         ListenerCallback(null);

         _logger.LogDebug("Http Listening Stop");
         _listener.Close();
      }


      public void NonblockingListener() {
         IAsyncResult result = _listener.BeginGetContext(ListenerCallback, _listener);
         result.AsyncWaitHandle.WaitOne();
      }


      public void ListenerCallback(IAsyncResult result) {

       if(_cancellationToken.IsCancellationRequested)return;

         _listener = (HttpListener)result.AsyncState;


         HttpListenerContext context = _listener.EndGetContext(result);
         HttpListenerRequest request = context.Request;

         //processing code
         EnqueUrl(request);
      }

Upvotes: 2

Related Questions