Hel*_*aon 8 .net wpf signalr owin
我们的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;
}
Run Code Online (Sandbox Code Playgroud)
对myWebApp.Dispose()的调用引发了'System.ObjectDisposedException'.难道我做错了什么?Microsoft.Owin.*dll具有版本2.1.0和SignalR自托管2.0.3
更新:事实证明这是我在visual studio中可以看到的第一个机会异常,因为设置"破坏clr异常"是活动的.这个例外似乎是在内部处理的,并没有冒出我们的代码
小智 3
在探索Katana源代码后,我找到了这个问题的原因。这就是Microsoft.Owin.Host.HttpListener.OwinHttpListener.ProcessRequestsAsync()方法。它启动 while 循环,包含在 try-catch 部分_listener.GetContextAsync()调用私有实例。HttpListener
类还实现IDisposable并包含一个Dispose()方法。此方法处置私有HttpListener实例。
当您调用它时WebApp.Start(),它会返回一个 的实例IDisposable,该实例只有Dispose()方法,即 disposes OwinHttpListener。
因此,当您处置它时,您可以调用它的Dispose()方法OwinHttpListener,该方法会处置 private 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();
}
Run Code Online (Sandbox Code Playgroud)