Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cleanly interrupt HttpListener's BeginGetContext method

I am using a HttpListener and using BeginGetContext to get my context object. I want to cleanly shut down my HttpListener but if I attempt to do a Close on the listener I get a exception and it causes my program to exit.

using System;
using System.Net;

namespace Sandbox_Console
{
    class Program
    {
        public static void Main()
        {
            if (!HttpListener.IsSupported)
            {
                Console.WriteLine("Windows XP SP2 or Server 2003 is required to use the HttpListener class.");
                return;
            }

            // Create a listener.
            HttpListener listener = new HttpListener();
            listener.Prefixes.Add("http://vwdev.vw.local:8081/BitsTest/");
            listener.Start();
            Console.WriteLine("Listening...");

            listener.BeginGetContext(Context, listener);
            Console.ReadLine();

            listener.Close(); //Exception on this line, but not shown in Visual Studio
            Console.WriteLine("Stopped Listening..."); //This line is never reached.
            Console.ReadLine();

        }

        static void Context(IAsyncResult result)
        {
            HttpListener listener = (HttpListener)result.AsyncState;
            HttpListenerContext context = listener.EndGetContext(result);

            context.Response.Close();
            listener.BeginGetContext(Context, listener);
        }
    }
}

The program throws a exception on the listener.Close() however the error never gets shown in Visual Studio, the only note I get is the following in the Debug output screen:

A first chance exception of type 'System.ObjectDisposedException' occurred in System.dll
The program '[2568] Sandbox Console.vshost.exe: Managed (v4.0.30319)' has exited with code 0 (0x0).

I was able to get the real execption from windows Event Viewer

Application: Sandbox Console.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.ObjectDisposedException
Stack:
   at System.Net.HttpListener.EndGetContext(System.IAsyncResult)
   at Sandbox_Console.Program.Context(System.IAsyncResult)
   at System.Net.LazyAsyncResult.Complete(IntPtr)
   at System.Net.ListenerAsyncResult.WaitCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)
   at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)

What do I need to do so I can close my HttpListener cleanly?

like image 545
Scott Chamberlain Avatar asked Nov 12 '12 21:11

Scott Chamberlain


1 Answers

Context gets called one last time when you call Close, you must handle the object disposed exception that could get thrown

static void Context(IAsyncResult result)
{
    HttpListener listener = (HttpListener)result.AsyncState;

   try
   {
        //If we are not listening this line throws a ObjectDisposedException.
        HttpListenerContext context = listener.EndGetContext(result);

        context.Response.Close();
        listener.BeginGetContext(Context, listener);
   }
   catch (ObjectDisposedException)
   {
       //Intentionally not doing anything with the exception.
   }
}
like image 129
Scott Chamberlain Avatar answered Nov 15 '22 09:11

Scott Chamberlain