Question about Catch and exceptions
-
Wednesday, December 23, 2009 1:06 AMI am using Observable.FromAsyncPattern in a Silverlight app to wrap some old IAsyncResult code. Everything works fine in Subscribe when it succeeds, but when the async End function throws an exception, I don't seem to know where to catch it.
I'm guessing the Observable<T>.Catch() method might be what I want, but the only reference I've seen is a video talking about it and I can't seem to find any example code of how to use it. Does anyone have an example of how I might write a method/lambda expression that catches an exception in this scenario?
Thanks!
All Replies
-
Wednesday, December 23, 2009 1:28 AM
Hi Andy,
there's several ways to deal with exceptions. the most simple one is to pass a second argument to your Subscribe call.
e.g.:
IObservable<string> x = Observable.FromAsyncPattern(...);
x.Subscribe(value=>HtmlPage.Window.Alert(value), error=>HtmlPage.Window.Alert(error.Message));
if you want to do more operations on the stream, you can use the Catch operator.
One way is to silence the catch: e.g. x.Catch(Observable.Empty<string>()).Subscibe(...)
another way is to write a catch block, in Rx, the catch block returns a new observable that "repairs" the original source:
x.Catch<ArgumentNullException>(error=> Observable.Return("The operation failed.")).Subscribe(...);
this sample will send the string "The operation failed" to the OnNext handler if an exception happens.
Hope this helps.
Jeffrey- Proposed As Answer by Jeffrey van Gogh - MS Wednesday, December 23, 2009 1:28 AM
- Marked As Answer by Andy N3 Wednesday, December 23, 2009 5:08 PM
-
Wednesday, December 23, 2009 5:08 PMThanks Jeffrey, that's exactly what I was looking for!
-
Thursday, May 19, 2011 1:27 AM
Jeff,
Is there a way to resume processing with the next element in the original observable sequence in the Catch operator instead of generating a new sequence?
Thx.
-Abhijeet
-
Thursday, May 19, 2011 9:49 AM
Hi Abhijeet,
This is not possible. The OnError notification represents a critical error, that terminates the stream. Similarly, enumerables can't yield values after an exception has been raised. Consider the following.
void Main() { var e = Get().GetEnumerator(); e.MoveNext(); e.MoveNext(); try{ e.MoveNext(); }catch{} e.MoveNext(); Console.WriteLine(e.Current); // will output 2 (not 3) } public IEnumerable Get() { yield return 1; yield return 2; throw new Exception("test"); yield return 3; // you can never read this value }
One option is for the "source" to use Notification<T> (or your own custom envelope type) instead.
public IObservable<Notification<int>> MyObservable() { return Observable.Create<Notification<int>>(o => { o.OnNext(new Notification<int>.OnNext(42)); o.OnNext(new Notification<int>.OnError(new Exception("error1"))); o.OnNext(new Notification<int>.OnNext(43)); o.OnNext(new Notification<int>.OnError(new Exception("error2"))); o.OnNext(new Notification<int>.OnNext(44)); o.OnNext(new Notification<int>.OnError(new Exception("error3"))); return () => {}; }); }
Hope that helps.
James
James Miles http://enumeratethis.com

