8

Tôi có phần mới đối với Rx.NET. Có thể bắt một ngoại lệ có thể được ném bởi bất kỳ người đăng ký nào không? Hãy thực hiện theo các bước sau ...Ghi ngoại lệ có thể được ném từ Đăng ký OnNext Action

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

Hiện tại tôi đang bắt trên cơ sở thuê bao với một ví dụ sau đây. Việc thực hiện mà chỉ sử dụng một ManualResetEvent để đánh thức một chủ đề chờ đợi.

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

và sử dụng nó như vậy ...

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

tôi cảm thấy như phải có một cách nào đó tốt hơn. Tất cả các khả năng xử lý lỗi trong Rx.NET có đặc biệt để xử lý các lỗi quan sát được không?

EDIT: Theo yêu cầu, triển khai của tôi là https://gist.github.com/1409829 (giao diện và triển khai được tách thành các hội đồng khác nhau trong mã sản phẩm). Phản hồi được hoan nghênh. Điều này có vẻ ngớ ngẩn, nhưng tôi đang sử dụng lâu đài windsor để quản lý nhiều người đăng ký Rx khác nhau. catcher ngoại lệ này được đăng ký với container như thế này

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

Nó sau đó sẽ được sử dụng như thế này ở đâu observable là thể hiện của IObservable:

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); 

Trả lời

8

Việc xây dựng trong điều hành Quan sát không làm những gì bạn đang yêu cầu theo mặc định (giống như các sự kiện), nhưng bạn có thể tạo một phương thức mở rộng để thực hiện việc này.

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

Sau đó, bất kỳ quan sát nào có thể được bao bọc bằng phương pháp này để có được hành vi bạn mô tả.

+0

Cảm ơn, bạn đã trả lời câu hỏi của mình, nhưng bạn có chắc chắn rằng việc thử/nắm bắt xung quanh OnNext sẽ bắt ngoại lệ? Người ta có thể dễ dàng làm một cái gì đó với IObservable trả về mà sẽ gây ra mã đăng ký được thực thi trên một thread khác. Ban đầu tôi đã cố gắng để thử một/try xung quanh cuộc gọi Subject.OnNext của tôi nhưng ngoại lệ đã không bị bắt. Tuy nhiên tôi có thể tạo ra một phương pháp SubscribeWithExceptionHandling hoặc một cái gì đó. – drstevens

+1

@drstevens Nó sẽ bắt ngoại lệ từ cùng một luồng. Nếu người quan sát của bạn đang tung ra các hoạt động không đồng bộ của chính nó mà ném ngoại lệ, điều này sẽ không bắt được. –

+1

Cũng xem xét có bao nhiêu kết quả hoạt động Rx trong một chủ đề mới (hoặc nhiệm vụ trong hồ bơi), tôi sẽ nói rằng nó là khá có khả năng đó sẽ là trường hợp. Ở giữa 'handler.FooStream' và' Subscribe' trong câu hỏi là một 'GroupByUntil (...). SelectMany (...). Buffer (với một thời gian)'. Tôi thực sự đã kết thúc việc tạo ra một 'TrackingWithCatch' theo ví dụ của bạn mà bắt ngoại lệ và sau đó sử dụng cùng một hành động được truyền cho trình xử lý OnError. – drstevens

Các vấn đề liên quan