在reactiveuiviewmodel (ReactiveObject)中取消异步任务
本文关键字:取消 异步 任务 reactiveuiviewmodel ReactiveObject | 更新日期: 2023-09-27 18:07:38
我目前正在试验ReactiveUI(5.5.1),我已经创建了一个ViewModel (ReactiveObject
的子类),它作为自动完成用于位置搜索(改编自mikebluestein/ReactiveUIDemo on github)。每次查询文本更改时,将调用一个REST服务,该服务返回所提交查询的匹配位置。
问题:正如您在下面的代码中看到的,DoSearchAsync(string query, CancellationToken cancellationToken)
是可取消的,但是,我不确定如何(以及在代码中的位置)实际取消任何搜索-因此使用CancellationToken.None
atm。在这个特定的用例中取消请求似乎有点过分,但是我想知道在这个reactiveUI/async-Task场景中如何启用取消。
public class ReactiveLocationSearchViewModel : ReactiveObject {
readonly ReactiveCommand searchCommand = new ReactiveCommand();
public ReactiveCommand SearchCommand { get { return searchCommand; } }
string query;
public string Query
{
get { return query; }
set { this.RaiseAndSetIfChanged(ref query, value); }
}
public ReactiveList<Location> ReactiveData { get; protected set; }
public ReactiveLocationSearchViewModel()
{
ReactiveData = new ReactiveList<Location>();
var results = searchCommand.RegisterAsyncTask<List<Location>>(async _ => await DoSearchAsync(query, CancellationToken.None));
this.ObservableForProperty<ReactiveLocationSearchViewModel, string>("Query")
.Throttle(new TimeSpan(700))
.Select(x => x.Value).DistinctUntilChanged()
.Where(x => !String.IsNullOrWhiteSpace(x))
.Subscribe(searchCommand.Execute);
results.Subscribe(list =>
{
ReactiveData.Clear();
ReactiveData.AddRange(list);
});
}
private async Task<List<Location>> DoSearchAsync(string query, CancellationToken cancellationToken)
{
// create default empty list
var locations = new List<Location>();
// only search if query is not empty
if (!string.IsNullOrEmpty(query))
{
ILocationService service = ServiceContainer.Resolve<ILocationService>();
locations = await service.GetLocationsAsync(query, cancellationToken);
}
return locations;
}
}
X没有内置这个功能,但是很容易伪造:
var results = searchCommand.RegisterAsync<List<Location>>(
_ => Observable.StartAsync(ct => DoSearchAsync(query, ct)));
在RxUI v6中,这是内置的:
searchCommand = ReactiveCommand.CreateAsyncTask(
(_, ct) => DoSearchAsync(query, ct));
更新ReactiveUI 9。x:
定义属性// using ReactiveUI.Fody
[Reactive]
public ReactiveCommand<TQuery, IEnumerable<TResult> SearchCommand { get; set; }
private CompositeDisposable Disposables { get; } = new CompositeDisposable();
构造函数中的// hook up the command
var searchCommand = ReactiveCommand.CreateFromTask<TQuery, IEnumerable<TResult>>((query, ct) => DoSearchAsync(query, ct)));
SearchCommand = searchCommand;
// don't forget to subscribe and dispose
searchCommand
.Subscribe(result => Result = result)
.DisposeWith(Disposables);
// hook up the command
var searchCommand = ReactiveCommand.CreateFromTask<TQuery, IEnumerable<TResult>>((query, ct) => DoSearchAsync(query, ct)));
SearchCommand = searchCommand;
// don't forget to subscribe and dispose
searchCommand
.Subscribe(result => Result = result)
.DisposeWith(Disposables);