After studying the source code of Katana, I found the cause of this problem. This is the Microsoft.Owin.Host.HttpListener.OwinHttpListener.ProcessRequestsAsync() method. It starts a while loop containing a call to _listener.GetContextAsync() private HttpListener instance in the try-catch section.
The class also implements IDisposable and contains the Dispose() method. This method provides a private HttpListener instance.
When you call WebApp.Start() , it returns an instance of IDisposable , which has only the Dispose() method, which has an OwinHttpListener .
So, when you destroy it, you call its Dispose() OwinHttpListener , which provides a private HttpListener .
But at the same time, ProcessRequestsAsync() throws _listener.GetContextAsync() , but _listener already placed and throws an ObjectDisposedException . catch locks the exception record and returns from ProcessRequestsAsync() .
I think double check lock in ProcessRequestsAsync() might be a good option.
private async void ProcessRequestsAsync() { while (_listener.IsListening && CanAcceptMoreRequests) { Interlocked.Increment(ref _currentOutstandingAccepts); HttpListenerContext context; try { context = await _listener.GetContextAsync(); } (SOME_OTHER_CATCHES) catch (ObjectDisposedException ode) { // These happen if HttpListener has been disposed Interlocked.Decrement(ref _currentOutstandingAccepts); LogHelper.LogException(_logger, "Accept", ode); return; } (SOME_OTHER_CODE) } } public void Dispose() { if (_listener.IsListening) { _listener.Stop(); } ((IDisposable)_listener).Dispose(); }
Tim
source share