8

से फेंक दिया जा सकता अपवाद जो मैं Rx.NET के लिए कुछ नया हूँ। क्या किसी अपवाद को पकड़ना संभव है जिसे किसी भी ग्राहक द्वारा फेंक दिया जा सकता है? निम्नलिखित ले लो ...एक अपवाद कार्यवाही

handler.FooStream.Subscribe(
      _ => throw new Exception("Bar"), 
      _ => { }); 

वर्तमान में मैं निम्नलिखित के उदाहरण के साथ प्रति सदस्यता आधार पर पकड़ रहा हूं। जिसका कार्यान्वयन केवल प्रतीक्षा थ्रेड उठाने के लिए मैन्युअल रीसेट इवेंट का उपयोग करता है।

public interface IExceptionCatcher 
{ 
    Action<T> Exec<T>(Action<T> action); 
} 

और इतने की तरह इसे का उपयोग ...

handler.FooStream.Subscribe(
      _exceptionCatcher.Exec<Foo>(_ => throw new Exception("Bar")), //It's disappointing that this generic type can't be inferred 
      _ => { }); 

मुझे लगता है कि वहाँ कुछ बेहतर तरीका होना चाहिए। आरएक्स.NET में विशेष रूप से त्रुटियों के अवलोकनों से निपटने के लिए सभी त्रुटि हैंडलिंग क्षमताओं क्या हैं?

संपादित करें: प्रति अनुरोध, मेरा कार्यान्वयन https://gist.github.com/1409829 (इंटरफ़ेस और कार्यान्वयन प्रोड कोड में विभिन्न असेंबली में अलग किया गया है)। प्रतिक्रिया का स्वागत है। यह मूर्खतापूर्ण प्रतीत हो सकता है, लेकिन मैं कई अलग-अलग आरएक्स ग्राहकों को प्रबंधित करने के लिए महल विंडसर का उपयोग कर रहा हूं।

var exceptionCatcher = 
    new ExceptionCatcher(e => 
           { 
            Logger.FatalException(
             "Exception caught, shutting down.", e); 
            // Deal with unmanaged resources here 
           }, false); 


/* 
* Normally the code below exists in some class managed by an IoC container. 
* 'catcher' would be provided by the container. 
*/ 
observable /* do some filtering, selecting, grouping etc */ 
    .SubscribeWithExceptionCatching(processItems, catcher); 

उत्तर

8

निर्मित प्रत्यक्ष ऑपरेटरों तुम क्या हो ऐसा नहीं करते हैं: यह अपवाद पकड़ने वाला इस

windsorContainer.Register(Component.For<IExceptionCatcher>().Instance(catcher)); 

तरह कंटेनर यह तो इस तरह इस्तेमाल किया जाएगा जहां observable IObservable का उदाहरण है के साथ पंजीकृत है डिफ़ॉल्ट रूप से पूछना (घटनाओं की तरह), लेकिन आप एक विस्तार विधि बना सकते हैं जो ऐसा करेगा।

public static IObservable<T> IgnoreObserverExceptions<T, TException>(
           this IObservable<T> source 
           ) where TException : Exception 
{ 
    return Observable.CreateWithDisposable<T>(
     o => source.Subscribe(
      v => { try { o.OnNext(v); } 
        catch (TException) { } 
      }, 
      ex => o.OnError(ex), 
      () => o.OnCompleted() 
      )); 
} 

तब आपके द्वारा वर्णित व्यवहार प्राप्त करने के लिए इस विधि द्वारा किसी भी अवलोकन योग्य को लपेटा जा सकता है।

+0

धन्यवाद, आपने मेरे प्रश्न का उत्तर दिया, लेकिन क्या आप सुनिश्चित हैं कि ऑननेक्स्ट के आसपास आपके प्रयास/पकड़ अपवादों को पकड़ लेंगे? कोई लौटा IObservable के साथ बहुत आसानी से कुछ कर सकता है जो सब्स्क्राइब किए गए कोड को किसी अन्य थ्रेड पर निष्पादित कर देगा। मैंने मूल रूप से अपने विषय के चारों ओर एक कोशिश/पकड़ लगाने की कोशिश की। अगला नाम लेकिन अपवाद पकड़े नहीं गए थे। हालांकि मैं एक सदस्यता WithException हैंडलिंग विधि या कुछ बना सकता था। – drstevens

+1

@drstevens यह एक ही थ्रेड से अपवाद पकड़ लेगा। यदि आपका पर्यवेक्षक एसिंक ऑपरेशंस लॉन्च कर रहा है जो अपवाद फेंकता है, तो यह उनको पकड़ नहीं पाएगा। –

+1

अच्छी तरह से विचार करते हुए कि आरएक्स परिचालनों में से कितने नए धागे (या पूल में कार्य) में परिणाम होता है, मैं कहूंगा कि यह मामला काफी संभावना है। प्रश्न में 'हैंडलर.फूस्ट्रीम' और 'सब्सक्राइब' के बीच में 'GroupByUntil (...) है। चुनें (...)। बफर (एक समय के साथ) '। मैं वास्तव में आपके उदाहरण के बाद 'SubscribeWithCatch' बनाने का अंत कर रहा हूं जो अपवाद को पकड़ता है और फिर ऑनरर हैंडलर को पास की गई एक ही क्रिया का उपयोग करता है। – drstevens