处置Microsoft.Owin.Hosting.WebApp会抛出'System.ObjectDisposedException'

时间:2014-04-10 08:09:40

标签: .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;
    }

对myWebApp.Dispose()的调用引发了一个System.ObjectDisposedException&#39;。 难道我做错了什么? Microsoft.Owin。* dll具有版本2.1.0和SignalR自托管2.0.3

UPDATE :原来这是我在visual studio中可以看到的第一个机会异常,因为设置&#34;打破clr异常&#34;活跃。这个异常似乎是在内部处理的,并没有冒出我们的代码

1 个答案:

答案 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已经处理并抛出ObjectDisposedExceptioncatch阻止记录异常并从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();
}