The code below always causes an exception on Windows. I am using .NET Core 2.2.
var l = new System.Net.HttpListener() { Prefixes = { "http://+/foo/" } };
l.Start();
l.BeginGetContext((f) => { }, null);
l.Stop();
l.Start();
l.BeginGetContext((f) => { }, null);
Message: System.ObjectDisposedException : Cannot access a disposed object.
Object name: 'System.Threading.ThreadPoolBoundHandle'.
at System.Threading.ThreadPoolBoundHandle.EnsureNotDisposed()
at System.Threading.ThreadPoolBoundHandle.AllocateNativeOverlapped(IOCompletionCallback callback, Object state, Object pinData)
at System.Net.AsyncRequestContext.Allocate(ThreadPoolBoundHandle boundHandle, UInt32 size)
at System.Net.ListenerAsyncResult..ctor(HttpListener listener, Object userState, AsyncCallback callback)
at System.Net.HttpListener.BeginGetContext(AsyncCallback callback, Object state)
The documentation states that it is valid to call .Stop() followed by .Start(), so I don't believe we would expect this code to throw: https://docs.microsoft.com/en-us/dotnet/api/system.net.httplistener.stop?view=netcore-2.2#remarks
I noticed this problem when porting an application from .NET Framework 4.5 to .NET Core 2.2 (that is, the code above does not throw on .NET Framework.) The ThreadPoolBoundHandle appears to be handled quite differently in .NET Core, and this appears to be specific to Windows.
On Windows, _requestQueueBoundHandle is created lazily the first time it is accessed. Stop() calls CloseRequestQueueHandle() which disposes _requestQueueBoundHandle without setting it to null, and calling Start() does not recreate it. So the next call to BeginGetContext() ends up using a handle that was disposed.
https://github.com/dotnet/corefx/blob/master/src/System.Net.HttpListener/src/System/Net/Windows/HttpListener.Windows.cs#L453
The code below always causes an exception on Windows. I am using .NET Core 2.2.
The documentation states that it is valid to call
.Stop()followed by.Start(), so I don't believe we would expect this code to throw: https://docs.microsoft.com/en-us/dotnet/api/system.net.httplistener.stop?view=netcore-2.2#remarksI noticed this problem when porting an application from .NET Framework 4.5 to .NET Core 2.2 (that is, the code above does not throw on .NET Framework.) The
ThreadPoolBoundHandleappears to be handled quite differently in .NET Core, and this appears to be specific to Windows.On Windows,
_requestQueueBoundHandleis created lazily the first time it is accessed.Stop()callsCloseRequestQueueHandle()which disposes_requestQueueBoundHandlewithout setting it tonull, and callingStart()does not recreate it. So the next call toBeginGetContext()ends up using a handle that was disposed.https://github.com/dotnet/corefx/blob/master/src/System.Net.HttpListener/src/System/Net/Windows/HttpListener.Windows.cs#L453