2014-04-10 29 views
8

'u atıyor WPF uygulamasında kendiliğinden barındırılan bir SignalR sunucumuz var. WebApp, uygulama başlangıcında başlatılır. Uygulama çıkışında WebApp'ı elden çıkarırız.Microsoft.Owin.Hosting.WebApp ürününü atma 'System.ObjectDisposedException'

public void Start() 
    { 
     myWebApp = WebApp.Start<MyApp>(url); 
    } 

    private void Dispose(bool isDisposing) 
    { 
     if (disposed) return; 

     if (isDisposing) 
      myWebApp.Dispose(); 

     disposed = true; 
    } 

myWebApp.Dispose() çağrısı bir 'System.ObjectDisposedException' yükseltir. Yanlış bir şey yapıyorum? . Bu ayarı "üzerine kırmak çünkü görsel stüdyoda görebileceğiniz ilk şans istisnadır çıkıyor: Microsoft.Owin * DLL sürüm 2.1.0 ve SignalR öz ana 2.0.3

GÜNCELLEME var clr istisnaları "etkin. Bu istisna dahili olarak ele alınmış gibi gözüküyor ve bizim kodumuzun içine girmiyor gibi gözüküyor

+0

O sizin durumunuzda ilk şans olabilir ama: 'appBuilder.UseNLog()' o Hata olarak istisna kaydeder. – SerG

cevap

3

Katana kaynak kodunu araştırdıktan sonra, bu sorunun nedenini buldum. Microsoft.Owin.Host.HttpListener.OwinHttpListener.ProcessRequestsAsync() yöntemidir. Try-catch bölümünde özel bir HttpListener örneğinin _listener.GetContextAsync() çağrısını içeren döngü sırasında başlar.

Ayrıca sınıf IDisposable uygular ve Dispose() yöntemini içerir. Bu yöntem, özel HttpListener örneğini kullanır. Aradığınızda

WebApp.Start() sadece OwinHttpListener elden Dispose() yöntemi, sahip olduğu, IDisposable bir örneğini döndürür.

Bu nedenle, attığınız zaman, numaralı Dispose() yöntemini çağırın. Özel HttpListener.

Ama aynı zamanda ProcessRequestsAsync(), _listener.GetContextAsync()'u çağırır, ancak _listener zaten atılır ve ObjectDisposedException'u atar. catch özel durumu günlüğe kaydeder ve ProcessRequestsAsync()'dan döndürür.

Sanırım, ProcessRequestsAsync() numaralı çifte kontrol kilidi iyi bir seçenek olabilir. NLog katman kullanılırsa

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(); 
} 
+0

Yani Katana'yı yeniden yazmadan sorunu çözmenin bir yolu yok. Doğru mu? – SerG

+1

@SerG evet, öyle. Tek yapabileceğiniz, WebApp.Start(), undisposed tarafından döndürülen nesneyi bırakmaktır. – Tim

+0

Çift denetimli kilitlemenin burada nerede yardımcı olacağından emin değilim. Bununla birlikte, Dispose yönteminin, dinleyicinin altında imha edilirken hala bir şeyler yapmaya çalışan asenkron sürecini kapatmak için daha fazlasını yapması gerektiği gibi görünüyor. –

İlgili konular