Search code examples
c#.netmultithreadingnancyhttplistener

Nancyfx self-hosting cannot stop HttpListener


I have an app, which has a rest-service based on NancyFx and i find it very cool framework. But i have a very big problem with stopping it. My host class looks like this:

public class RestHost : IStartStopAble
{
    private readonly string _uri;
    private readonly IWindsorContainer _container;
    private NancyHost _host;
    private Thread _wsThread;
    private WindsorBootstrapper _windsorBootstrapper;

    public RestHost(string uri, IWindsorContainer container)
    {
        _uri = uri;
        _container = container;
    }

    public void Start()
    {
        var uri = new Uri(_uri);

        _windsorBootstrapper = new WindsorBootstrapper(_container);
        _host = new NancyHost(uri, _windsorBootstrapper);

        _host.Start();
    }

    public void Stop()
    {
        _host.Dispose();
    }
}

AS you can see, i use windsor along with Nancy. Everything works great, i call Start, Stop and constructor from main thread, but when i Dispose my host i catch this:

 HttpListener: HttpListenerException: The I/O operation has been aborted because of either a thread exit or an application request

exception. I found this paper: http://maykov.blogspot.ru/2009/02/c-httplistener-httplistenerexception-io.html but i use main thread and don't understand how can i "Save" the thread, in which HttpListener is created and, also, how can i pass it to Nancy.

I'll be very gratefull for any help, still i don't even know, what can i do with HttpListener exception in core of .Net framework.


Solution

  • You may remember the SynchronizationContext:

    public void Start()
    {
        // init _host ...
    
        _syncContext = SynchronizationContext.Current;
        _host.Start();
    }
    
    public void Stop()
    {
        if (_syncContext == SynchronizationContext.Current)
        {
            _host.Dispose();
        }
        else
        {
            _syncContext.Post((state) =>
            {
                _host.Dispose();
            }
            , null);
        }
    }