System.reactive 搜索中的被动扩展开关()

System.reactive 搜索中的被动扩展开关(),system.reactive,reactive-programming,System.reactive,Reactive Programming,经典的实时搜索示例: var searchResults = from input in textBoxChanged from results in GetDataAsync(input) select results; GetDataAsync返回一个: Task<List<DataRecord>> 任务 这显然是一个竞争条件,因此如果由第二个输入触发的搜索在第一个输入之前返回,则

经典的实时搜索示例:

var searchResults = from input in textBoxChanged
                    from results in GetDataAsync(input)
                    select results;
GetDataAsync返回一个:

 Task<List<DataRecord>>
任务
这显然是一个竞争条件,因此如果由第二个输入触发的搜索在第一个输入之前返回,则第一个输入的结果在第一个输入之后,因此给我错误的数据

我到处都在读到.Switch()操作符会神奇地解决这个问题,但是如何解决呢

.Switch()仅存在于:

 IObservable<IObservable<T>>
IObservable
假设 我假设textBoxChanged是由以下内容创建的:

var textBoxChanged = Observable.FromEventPattern(x, "TextChanged")
                               .Select(evt => ((TextBox)evt.Sender).Text);
使用SelectMany时防止竞争情况 从。。。从…起在LINQ中,理解转换为
SelectMany
,这就是您正在使用的。Rx足够智能,可以将
GetDataAsync(input)
返回的
任务
转换为
IObservable

问题在于,您希望阻止从除最近提交的搜索请求之外的所有搜索请求返回结果

要做到这一点,您可以利用。其签名如下:

public static IObservable<TSource> TakeUntil<TSource, TOther>(
    this IObservable<TSource> source,
    IObservable<TOther> other
)
这将阻止竞争条件,但也将订阅两次textBoxChanged

改用
开关
这是一种非常有用的模式,使用
Switch()
操作符引入了一种替代方法,该操作符还负责双重订阅

不要使用
SelectMany
,只需将输入直接投射到搜索查询中,这将给出一个返回类型
IObservable
var searchResults = from input in textBoxChanged
                    from results in GetDataAsync(input).ToObservable().TakeUntil(textBoxChanged)
                    select results;
var searchResults = (from input in textBoxChanged
                     select GetSearchResults(input).ToObservable())
                    .Switch();