取消/忽略ReactiveUI中的ReactiveAsyncCommand的结果

本文关键字:ReactiveAsyncCommand 结果 中的 ReactiveUI 忽略 取消 | 更新日期: 2023-09-27 18:25:54

当用户在文本框中输入时,我有一个ReactiveAsyncCommand来执行搜索,设置如下:

var results = SearchCommand.RegisterAsyncFunction(term => 
PerformSearch((string)term));
this.ObservableForProperty(x => x.SearchTerm)
.Throttle(TimeSpan.FromMilliseconds(800))
.Select(x => x.Value).DistinctUntilChanged()
.Where(x => !String.IsNullOrWhiteSpace(x))
.InvokeCommand(SearchCommand);
_SearchResults = results.ToProperty(this, x => x.SearchResults);

问题是,由于需要执行数据库查询,并且显示了一个过时的结果,搜索功能可能会非常慢,我认为这是由于ReactiveAsyncCommand在当前异步任务完成之前没有再次运行。

所以我的问题是,我如何取消正在运行的异步任务,然后用当前搜索词重新开始,或者如果结果不是针对当前搜索词的,我如何完全删除结果。

这似乎与本讨论的第二部分相同,但我不确定如何将其应用于我的代码,因为我的搜索代码返回的是IEnumerable而不是IOobservable。

请注意RxUI 4,因为它是一个.NET 4应用程序。

更新:PerformSearch方法

private List<WizardLocationSearchResult> PerformSearch(string searchTerm)
{
var results = new List<WizardLocationSearchResult>();
bool isMatch = false;

if (Regex.IsMatch(searchTerm, _postcodeRegex, RegexOptions.IgnoreCase))
{
    var locationResult = _locationService.GetByPostcode(searchTerm);
    _locationService.DeepLoad(locationResult, true, Data.DeepLoadType.IncludeChildren, typeof(TList<EnterpriseAndHolding>));
    results.AddRange(ProcessLocationSearches(locationResult));
    isMatch = true;
}

if (!isMatch)
{
    var query = new LocationParameterBuilder(true, false);
    string formattedSearchTerm = searchTerm + "%";
    query.AppendLike(LocationColumn.Address1, formattedSearchTerm);
    query.AppendLike(LocationColumn.Address2, formattedSearchTerm);
    query.AppendLike(LocationColumn.Town, formattedSearchTerm);
    query.AppendLike(LocationColumn.PostalTown, formattedSearchTerm);
    query.AppendLike(LocationColumn.County, formattedSearchTerm);
    var locationResult = _locationService.Find(query.GetParameters());
    _locationService.DeepLoad(locationResult, true, Data.DeepLoadType.IncludeChildren, typeof(TList<EnterpriseAndHolding>));
    results.AddRange(ProcessLocationSearches(locationResult));
}
return results;
}

取消/忽略ReactiveUI中的ReactiveAsyncCommand的结果

ReactiveAsyncCommand背后的理念是有意限制飞行中请求的数量。在这种情况下,您想忘记这个约束,所以让我们使用常规的ReactiveCommand

SearchCommand
    .Select(x => Observable.Start(() => PerformSearch(x), RxApp.TaskPoolScheduler))
    .Switch()
    .ToProperty(this, x => x.SearchResults);

请注意,这里的Select.SwitchSelectMany类似,只是它将始终保持输入的顺序,同时如果旧输入没有及时完成,则丢弃旧输入。

等等取消代币来源等等TPL

在这种情况下,底层方法本身(_locationService.DeepLoad)是同步的——不可能以安全的方式取消该方法,所以我们只能让取消的结果运行到完成,并忽略结果,这就是我们在这里要做的。

编辑:这里有一个丑陋的破解方法来判断物品是否在飞行中:

SearchCommand
    .Do(x => Interlocked.Increment(ref searchesInFlight))
    .Select(x => Observable.Start(() => PerformSearch(x), RxApp.TaskPoolScheduler).Do(x => Interlocked.Decrement(ref searchesInFlight)))
    .Switch()        
    .ToProperty(this, x => x.SearchResults);
相关文章:
  • 没有找到相关文章