假设
我将假设 textBoxChanged 是由以下内容创建的:
var textBoxChanged = Observable.FromEventPattern(x, "TextChanged")
.Select(evt => ((TextBox)evt.Sender).Text);
使用 SelectMany 时防止竞争条件
from... from... 在 LINQ 理解中转换为 a SelectMany
,这就是您正在使用的。Rx 足够聪明,可以将Task<List<DataRecord>>
返回的 byGetDataAsync(input)
转换为IObservable<List<DataRecord>>
.
问题是您希望防止从除最近提交的搜索请求之外的所有搜索请求中返回结果。
为此,您可以利用TakeUntil
. 它具有以下签名:
public static IObservable<TSource> TakeUntil<TSource, TOther>(
this IObservable<TSource> source,
IObservable<TOther> other
)
它从源可观察序列返回值,直到另一个可观察序列产生值。
我们可以这样使用它:
var searchResults = from input in textBoxChanged
from results in GetDataAsync(input).ToObservable().TakeUntil(textBoxChanged)
select results;
这将防止竞争条件,但也会订阅两次 textBoxChanged。
Switch
改为使用
这是一种非常有用的模式,因此使用运算符引入了另一种方法,该Switch()
运算符也负责双重订阅。
而不是使用SelectMany
,只需将输入直接投影到搜索查询中 - 这将给出一个返回类型IObservable<IObservable<List<DataRecord>>
,一个流的流。Switch 会从一个流跳到另一个流,只返回最近的流。这相当于 SelectMany/TakeUntil 组合:
var searchResults = (from input in textBoxChanged
select GetSearchResults(input).ToObservable())
.Switch();
我强烈建议查看 Rx Hands on Lab,它更详细地解释了这一点。