我对ReactiveUI相对较新,并且正在尝试从ReactiveCommand异步执行数据库查询。据我所知,问题不在于执行异步查询,而是当我尝试将结果加载到视图模型中的ReactiveList中时。我相信这是一个调度问题,但是我对RxUI不够熟悉,无法提出正确的方法。
我尝试使用带有ObserveOn的RxApp.TaskPoolScheduler和RxApp.MainThreadScheduler订阅视图模型中的命令,但似乎都没有帮助。
我的视图模型:
public class UsersViewModel : ReactiveObject, IRoutableViewModel
{
ReactiveList<LisUser> _users;
IUserManagementService UsersService { get; }
public IScreen HostScreen { get; }
public ReactiveCommand<Unit, IEnumerable<LisUser>> LoadUsers { get; }
public String UrlPathSegment => "users";
public ReactiveList<LisUser> Users
{
get => _users;
set => this.RaiseAndSetIfChanged(ref _users, value);
}
public UsersSubPageViewModel(
IScreen screen,
IUserManagementService usersService)
{
HostScreen = screen ?? throw new ArgumentNullException(nameof(screen));
UsersService =
usersService ?? throw new ArgumentNullException(nameof(usersService));
Users = new ReactiveList<LisUser>();
LoadUsers = ReactiveCommand.CreateFromTask(async () =>
{
return await UsersService.GetUsersAsync().ConfigureAwait(false);
});
LoadUsers
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(list =>
{
Users.Clear();
foreach (var u in list)
{
Users.Add(u);
}
});
}
}
我的观点:
public partial class UsersView : ReactiveUserControl<UsersViewModel>
{
public UsersPageView()
{
InitializeComponent();
this.WhenActivated(disposables =>
{
this.WhenAnyValue(x => x.ViewModel.LoadUsers)
.SelectMany(x => x.Execute())
.Subscribe()
.DisposeWith(disposables);
});
}
}
我要发生的事情是,当激活UsersView时,UsersService的GetUsers方法将异步执行并将返回的用户列表加载到Users ReactiveList中。相反,我在VS中看到一个新选项卡,标题为“找不到源”,并显示一条消息,提示“找不到RxApp.cs”。实际的异常是System.Exception,其中带有一条消息,指出“无法获取局部变量或参数的值,因为它在此指令指针处不可用,可能是因为它已被优化。”
所以,我的第一个问题是“这实际上是计划问题吗?”第二个问题是“我该如何解决?”
答案 0 :(得分:0)
。首先,如我的评论所述,不推荐使用activelist。
调用LoadUsers命令的方式存在问题。
一种是您可以在视图模型中执行WhenActivated。您从ISupportsActivation
派生视图模型,视图在调用WhenActivated时将在视图内部调用WhileActivated块。有关想法,请参见https://reactiveui.net/docs/handbook/when-activated/#viewmodels。
第二种方法是
this.WhenAnyValue(x => x.ViewModel.LoadUsers)
.Select(x => x.Execute())
.Switch()
.Subscribe()
.DisposeWith(disposables);
因此,上面说的是获取LoadUsers命令,获取可观察到的Execute(),Switch()意味着仅先订阅最新的,并在输入新值时处置旧的execute,然后订阅运行该命令,并设置为可能停止。
答案 1 :(得分:0)
问题似乎不是在计划中,而是与异步相关。
IUserManagementService引用了一个IUserRepository,该IUserRepository本身具有一个GetUsersAsync方法来实际查询数据库。 IUserManagementService的实际实现在对IUserRepository.GetUsersAsync的调用中缺少ConfigureAwait。在单元测试中这不是问题,但是一旦涉及到UI,肯定是一个问题。