Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stopping and restarting HttpListener?

I am working on an app that has an HttpListener. My goal is for the user to turn the listener off and on as they choose. I put the Listener in a new thread and I'm having a problem aborting that thread. I read somewhere that if you try to abort a thread that is in an unmanaged context, then as soon as it re-enters a managed context the ThreadAbortException will be fired. It appears that an HttpListener's GetContext() method is unmanaged because when I try to abort the thread nothing happens until I make a web request against my app. THEN the thread exits. The problem is when I attempt to kill the thread, I may start up the thread again later on the same port and an HttpListenerException goes off saying that the prefix is already registered.

How can I kill a cross thread HttpListener? Is there a managed alternative to GetContext() that will allow the thread to abort? Can I abort the thread in a way that unmanaged code will halt?

like image 399
Corey Ogburn Avatar asked Oct 24 '25 18:10

Corey Ogburn


2 Answers

What about something like:

public class XListener
{
    HttpListener listener;

    public XListener(string prefix)
    {
        listener = new HttpListener();
        listener.Prefixes.Add(prefix);
    }

    public void StartListen()
    {
        if (!listener.IsListening)
        {
            listener.Start();

            Task.Factory.StartNew(async () =>
            {
                while (true) await Listen(listener);
            }, TaskCreationOptions.LongRunning);

            Console.WriteLine("Listener started");
        }
    }

    public void StopListen()
    {
        if (listener.IsListening)
        {
            listener.Stop();
            Console.WriteLine("Listener stopped");
        }
    }

    private async Task Listen(HttpListener l)
    {
        try
        {
            var ctx = await l.GetContextAsync();

            var text = "Hello World";
            var buffer = Encoding.UTF8.GetBytes(text);

            using (var response = ctx.Response)
            {
                ctx.Response.ContentLength64 = buffer.Length;
                ctx.Response.OutputStream.Write(buffer, 0, buffer.Length);
            }
        }
        catch (HttpListenerException)
        {
            Console.WriteLine("screw you guys, I'm going home!");
        }
    }
}

Usage:

var x = new XListener("http://locahost:8080");

x.StartListen();
Thread.Sleep(500); // test purpose only

x.StopListen();
Thread.Sleep(500); // test purpose only

x.StartListen();

/* OUTPUT:
=> Listener started
=> Listener stopped
=> screw you guys, I'm going home!
=> Listener started */
like image 88
ebb Avatar answered Oct 26 '25 06:10

ebb


You need to signal the thread to call HttpListener.Stop() and wait for the thread to finish by calling Thread.Join()

like image 37
matt-dot-net Avatar answered Oct 26 '25 06:10

matt-dot-net