我们的WPF应用程序中有一个自托管的SignalR服务器。 WebApp在应用程序启动时启动。在应用程序退出时,我们处理WebApp。
public void Start()
{
myWebApp = WebApp.Start<MyApp>(url);
}
private void Dispose(bool isDisposing)
{
if (disposed) return;
if (isDisposing)
myWebApp.Dispose();
disposed = true;
}
对myWebApp.Dispose()的调用引发了一个System.ObjectDisposedException&#39;。 难道我做错了什么? Microsoft.Owin。* dll具有版本2.1.0和SignalR自托管2.0.3
UPDATE :原来这是我在visual studio中可以看到的第一个机会异常,因为设置&#34;打破clr异常&#34;活跃。这个异常似乎是在内部处理的,并没有冒出我们的代码
答案 0 :(得分:3)
在探索Katana源代码后,我发现了这个问题的原因。这是Microsoft.Owin.Host.HttpListener.OwinHttpListener.ProcessRequestsAsync()
方法。它在try-catch部分中启动while循环,包含_listener.GetContextAsync()
私有HttpListener
实例的调用。
此类实现IDisposable
并包含Dispose()
方法。此方法处理私有HttpListener
实例。
当您致电WebApp.Start()
时,它会返回IDisposable
的实例,该实例只有Dispose()
方法,可以处置OwinHttpListener
。
因此,当您处置它时,您调用其Dispose()
OwinHttpListener
方法,该方法处置私有HttpListener
。
但同时ProcessRequestsAsync()
调用_listener.GetContextAsync()
,但_listener
已经处理并抛出ObjectDisposedException
。 catch
阻止记录异常并从ProcessRequestsAsync()
返回。
我认为,ProcessRequestsAsync()
中的双重检查锁可能是一个不错的选择。
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();
}