roa*_*242 4 c# system.reactive reactiveui
我正在尝试使用Rx + ReactiveUI来解决我的第一个任务,并且正在寻找解决任务的最佳实践,显示一个输入框,一旦用户开始输入就会显示建议.
根据以下代码示例,异步加载建议的最佳方法是什么?使用Subscribe还是使用Select Many?或者有更好的方法来实现这两个目标吗?
this.SearchTerms = this.ObservableForProperty(x => x.SearchTerm)
.Throttle(SuggestionThrottle, RxApp.MainThreadScheduler)
.Value()
.SelectMany(async s => await this.LoadSearchSuggestions(s)); // 1st Possibility
this.SearchTerms.Subscribe(this.LoadSearchSuggestions); // 2nd Possibility
Run Code Online (Sandbox Code Playgroud)
Dav*_*ton 14
你必须Subscribe要么打电话.
Rx中的查询使用延迟评估,这意味着仅定义查询不会启动它.延迟评估允许您通过有条件地应用运算符来构建查询,仅定义查询一次并将其存储在字段中以供日后使用,或者在调用之前传递引用而不会产生任何副作用Subscribe.
不调用Subscribe您的查询将保持不活动状态.
Subscribe通过传递到观察的激活查询您IObserver<T>,或者您可以使用它的重载允许您提供OnNext,OnError和/或OnCompleted处理个人,其中的Rx转换成IObserver<T>适合你.它是IObserver<T>接收查询通知的.
有一个无参数的重载,Subscribe它在内部使用一个静默的观察者,目的是只为其副作用启动查询.例如,在您的情况下,如果您要用于SelectMany完成加载建议的所有工作而您不需要单独的IObserver<T>,那么您将通过调用无参数的重载来启动查询Subscribe.
在大多数情况下,您不应使用无参数的重载Subscribe.关键Subscribe是IObserver<T>您传递给它的(或单个处理程序)旨在导致查询的副作用.通过仅Subscribe在Do操作员或例如操作员中引起副作用,查询更容易推理和维护.
但是,有一个相当常见的情况是使用无参数重载是Subscribe有意义的:如果查询的副作用是由异步方法引起的,那么最好使用SelectMany无参数重载Subscribe.
原因很简单:SelectMany是顺序组合运算符,它使您可以将异步方法作为查询中的顺序步骤调用.因此,SelectMany将订阅的取消与取消异步计算联系起来.处理订阅(由IDisposble从调用返回的订阅表示Subscribe)导致CancellationToken由SelectMany运营商的特殊异步过载提供的信号用于取消.您的异步方法可以监视它CancellationToken以提前退出其计算.
没有任何重载Subscribe接受异步观察者,从而OnNext返回a Task.但即使您在OnNext处理程序中调用返回void的异步方法,也不会在处理订阅时发出异步方法的信号.
请注意,无论如何,您的两个代码示例都略有错误.第一个示例不需要async和await关键字.如上所述,有一些特殊的重载SelectMany接受一个Task<T>返回选择器功能,以及提供CancellationToken该功能的额外重载.你可能应该使用后者.
你的第二个例子不应该编译,假设LoadSearchSuggestions返回Task.(除非ReactiveUI库或您引用的其他库提供了一个Subscribe接受Task回复函数的重载,在这种情况下,您将不得不查阅他们的文档.)
除非后者,并假设您的其余查询是正确的,这是您应该做的:
this.SearchTerms = this.ObservableForProperty(x => x.SearchTerm)
.Throttle(SuggestionThrottle, RxApp.MainThreadScheduler)
.Value()
.SelectMany(LoadSearchSuggestionsAsync)
.Subscribe();
Run Code Online (Sandbox Code Playgroud)
在哪里LoadSearchSuggestionsAsync定义如下:
async Task<Unit> LoadSearchSuggestionsAsync(string term, CancellationToken cancel)
{
...
return Unit.Default;
}
Run Code Online (Sandbox Code Playgroud)
请注意,Unit表示Rx中的void.这是必需的,因为返回非泛型的异步方法Task不能用于SelectMany.如果您要返回实际数据,则只需替换Unit为您的数据类型即可.然后,您还可以传递OnNext处理程序Subscribe并对返回值执行某些操作,例如日志记录.