我有来自旧示例的代码(Reactive UI 4):
StartAsyncCommand = new ReactiveCommand();
StartAsyncCommand.RegisterAsyncAction(_ =>
{
Progress = 0;
var exe = Enumerable.Range(0, 10).Select(x =>
{
Thread.Sleep(100);
return x;
}).ToObservable();
exe.Subscribe(x =>Progress += 10);
});
它运行良好,用户界面不会被阻止,按钮被禁用,直到进度达到100%。
当我迁移到版本6时,我尝试了许多方法来实现相同的功能,但都没有成功。
这些是我的尝试:
1) 使用CreateAsyncObservable
GenerateCommand = ReactiveCommand.CreateAsyncObservable(canGenerate, x => DoSomething());
public IObservable<Unit> DoSomething()
{
var exe = Enumerable.Range(0, 10).Select(
x =>
{
Thread.Sleep(200);
return x;
}).ToObservable().ObserveOnDispatcher().SubscribeOn(NewThreadScheduler.Default);
exe.Subscribe(x =>
Progress += 10
);
return Observable.Return(new Unit());
}
它工作,但按钮不会禁用。
2) 带CreateAsyncTask
GenerateCommand = ReactiveCommand.CreateAsyncTask(canGenerate, x => DoSomething());
public async Task<Unit> DoSomething()
{
var exe = Enumerable.Range(0, 10).Select(
x =>
{
Thread.Sleep(200);
return x;
}).ToObservable().ObserveOnDispatcher().SubscribeOn(NewThreadScheduler.Default);
await exe;
exe.Subscribe(x =>
Progress+=10
);
return new Unit();
}
它可以工作,但按钮只能禁用,直到等待结束。
3) 基于WPF应用中后台线程上未运行的ReactiveUI 6异步命令
GenerateCommand = ReactiveCommand.CreateAsyncTask(canGenerate, x => DoSomething());
public async Task<Unit> DoSomething()
{
var execTask = Task.Factory.StartNew(() =>
{
var exe = Enumerable.Range(0, 10).Select(
x =>
{
Thread.Sleep(200);
return x;
}).ToObservable();
exe.Subscribe(x =>
Progress += 10
);
return new Unit();
});
return execTask.Result;
}
这引发了一个异常。
更新
4) Subscribe
命令:
GenerateCommand = ReactiveCommand.CreateAsyncObservable(canGenerate, x => DoSomething());
GenerateCommand.ObserveOnDispatcher().SubscribeOn(NewThreadScheduler.Default)
.Subscribe(x => Progress += 10);
public IObservable<int> DoSomething()
{
return = Observable.Range(0, 10).Select(
x =>
{
Thread.Sleep(200);
return x;
});
}
相同的结果。。。
如何使用版本6实现相同的功能?
我做错了什么?
这是一种非常奇怪的方式来做你想做的事情
StartAsyncCommand = ReactiveCommand.CreateAsyncObservable(_ =>
Observable.Timer(DateTimeOffset.Zero, TimeSpan.FromSeconds(1))
.Take(10)
.Scan(0, (acc,x) => acc + 10));
StartAsyncCommand.ToProperty(this, x => x.Progress, out progress);