如何将其从7.0转换为ReactiveCommand:
private void SetCanRunProcessCommand()
{
_runProcessCommand = new ReactiveAsyncCommand(CanRunProcess(null));
_runProcessCommand.RegisterAsyncAction(RunProcess);
_runProcessCommand.ThrownExceptions.Subscribe(OnError);
_runProcessCommand.AsyncStartedNotification.Subscribe(_ => IsBusy = true);
_runProcessCommand.AsyncCompletedNotification.Subscribe(x => IsBusy = false);
_runProcessCommand.AsyncCompletedNotification.Subscribe(_ => PerformPostRunImpl());
}
以下是我的尝试:
private void SetCanRunProcessCommand()
{
_runProcessCommand = ReactiveCommand.CreateFromTask((x) => Run(x), CanRunProcess(null));
_runProcessCommand.IsExecuting.ToProperty(this, x => x.IsBusy);
_runProcessCommand.ThrownExceptions.Subscribe(OnError);
}
private async Task Run(object param)
{
try
{
await RunProcess(param);
}
finally
{
PerformPostRunImpl();
}
}
这种方法的问题在于我现在无法控制调度程序。当我测试代码时,我无法使用TestScheduler
及时向前移动,因为代码不依赖于调度程序。
第二种方法是通过调度程序将ReactiveCommand.Create
与RxApp.ThreadPoolScheduler
一起使用,这将是单元测试中的CurrentThread。这就是我要做的,但还有其他问题。
ReactiveCommand.Create(function)
在之前的版本中与此相同:代码:
var command = ReactiveCommand.Create();
command.Subscribe(function);
但这不是因为第二次通话是由调度程序控制的。
这会产生另一个问题,因为RunProcess
包含一些需要在UI线程上进行的调用,因此我将得到跨线程异常。它在4.6.1 ReactiveUI中是如何工作的?我怎样才能回到那种行为?
如何在RunProcess
之后执行操作?最后似乎没有用。
简单示例:
public bool Validation()
{
return isValid(); Background
}
public void RunProcess()
{
LongRunning(); // Background
}
public void SetEverythingIsCorrect()
{
State = Success; // UI
}
我需要创建一个ReactiveCommand,它将在不同的调度程序上调用这3个方法。在测试中,我想使用TestScheduler,所以一切都应该是单线程的。像这样:
new TestScheduler().With(sched =>
{
Abc a = new Abc(_dialogService, _fileSystemHelper);
a.RunProcessCommand.Execute();
sched.AdvanceBy(1000);
Assert.AreEqual(State.Success, a.State);
});
验证时,应调用RunProcess TaskPoolScheduler 应该在MainThreadScheduler上调用SetEverythingIsCorrect。
我的最后一种方法与此类似:
protected internal async Task RunProcess(object obj)
{
await Observable.Start(Validation, RxApp.TaskpoolScheduler)
.Concat(Observable.Start(() => RunProcess(obj), RxApp.TaskpoolScheduler))
.Concat(Observable.Start(SetEverythingIsCorrect, RxApp.MainThreadScheduler))
.Finally(() =>
{
PerformPostRunImpl();
IsBusy = false;
});
}
_runProcessCommand = ReactiveCommand.CreateFromTask(() => RunProcess(null), CanRunProcess(null));