Rx:使用异步函数订阅并忽略错误

时间:2015-04-03 07:01:14

标签: asynchronous system.reactive

我想为observable中的每个项调用异步函数。在回答here时,解决方案是使用SelectMany。但是,如果抛出异步方法,则订阅将终止。我有以下解决方案,似乎有效:

obs.SelectMany(x => Observable
    .FromAsync(() => RunAsync())
    .Catch(Observable.Empty<string>()));

是否有更惯用的解决方案?

2 个答案:

答案 0 :(得分:1)

有一种标准方法可以观察RunAsync来电中发生的异常,并使用.Materialize()

.Materialize()方法将IObservable<T>序列转换为IObservable<Notification<T>>序列,您可以对OnNextOnErrorOnCompleted进行推理调用

我写了这个查询:

var obs = Observable.Range(0, 10);

obs
    .SelectMany(x =>
        Observable
            .FromAsync(() => RunAsync())
            .Materialize())
    .Where(x => x.Kind != NotificationKind.OnCompleted)
    .Select(x => x.HasValue ? x.Value : (x.Exception.Message + "!"))
    .Subscribe(x => x.Dump());

使用此支持代码:

private int counter = 0;
private Random rnd = new Random();

private System.Threading.Tasks.Task<string> RunAsync()
{
    return System.Threading.Tasks.Task.Factory.StartNew(() =>
    {
        System.Threading.Interlocked.Increment(ref counter);
        if (rnd.NextDouble() < 0.3)
        {
            throw new Exception(counter.ToString());
        }
        return counter.ToString();
    });
}

当我运行它时,我得到了这种输出:

2
4
5
1!
6
7
3!
10
8!
9

!结尾的每一行都是对RunAsync的调用,导致异常。

答案 1 :(得分:0)

您也可以使用OnErrorResumeNext。

obs.SelectMany(x => Observable
    .FromAsync(() => RunAsync())
    .OnErrorResumeNext(Observable.Empty<string>()));