我目前正在玩ReactiveUI(有一些Rx之前的经验)。 我正在尝试做的是处理某种火灾/忘记/通知工作流程。
基本上,我想执行和操作,然后在成功或失败时收到通知。但是,在执行下一个操作之前,我不想等待该操作完成,因此我实现了以下代码片段:
private ReactiveList<VerifiableString> _inputData = new ReactiveList<VerifiableString>();
private ReactiveList<VerifiableString> _savedData = new ReactiveList<VerifiableString>();
private Subject<VerifiableString> _stringSubject = new Subject<VerifiableString>();
private ReactiveCommand<Unit> _addCommand;
public MainViewModel()
{
for (int i = 0; i < 10; i++)
{
_inputData.Add(new VerifiableString{Value = Guid.NewGuid().ToString()});
}
var canExecute = this.WhenAny(x => x.InputData.Count, x => x.Value != 0);
AddCommand = ReactiveCommand.CreateAsyncTask(canExecute, x => SendStringForProcessingAsync());
AddCommand.ThrownExceptions.Subscribe(ex => MessageBox.Show(ex.ToString()));
_stringSubject.ObserveOn(RxApp.MainThreadScheduler).Subscribe(AddString, e => MessageBox.Show(e.Message));
}
private async Task<Unit> SendStringForProcessingAsync()
{
var item = InputData.First();
InputData.RemoveAt(0);
//intentionally not awaiting on this
PostNewItemAsync(item);
return new Unit();
}
private async Task PostNewItemAsync(VerifiableString item)
{
_stringSubject.OnNext(item);
await Task.Delay(1000);
item.Verified = true;
_stringSubject.OnNext(item);
}
此代码按我的预期工作。我可以根据需要多次调用该命令,获得调用该命令的即时通知,然后1s后,通知该命令已完成。
我有一种感觉,通过使用ReactiveCommand和Subject,我可能会忽略ReactiveUI的观点?此外,通过使用主题,我没有得到你直接使用ReactiveCommands可以观察到的那个可爱的ThrownError。
对于上下文,UI包含两个列表和一个按钮,单击该按钮可将字符串从一个列表移动到另一个列表,稍后,该字符串将使用“已验证”标志进行更新。
EDIT 20141023
现在我有了这个:
{
//...
AddCommand
.SelectMany(_ => Observable.FromAsync(SendStringForProcessingAsync))
.Catch(Observable.Return(new VerifiableString{Value = "What the hell !"}))
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(AddString);
AddCommand.ThrownExceptions.Subscribe(ex => Debug.WriteLine(ex));
//...
}
private async Task<VerifiableString> PostNewItemAsync(VerifiableString param, CancellationToken cancellationToken)
{
await Task.Delay(_random.Next(1000, 5000), cancellationToken);
param.Verified = VerifyState.Verified;
return param;
}
private async Task<VerifiableString> SendStringForProcessingAsync(CancellationToken t)
{
var item = InputData.First();
InputData.RemoveAt(0);
AddString(item);
return await PostNewItemAsync(item, t);
}
如果我在“SendStringForProcessingAsync”中抛出异常,我的“错误消息”会出现在我的列表中(尽管调试日志中没有任何内容)。但是,此时,我再也无法继续执行命令。
另外,我使用了Observable.FromAsync,因此我可以传递取消令牌,并取消飞行中的物品。我不能为我的生活,弄清楚如何访问CancellationTokenSource所以我可以取消这些东西......
我错过了一些明显的东西吗?
答案 0 :(得分:1)
如果您想退出RxCmd的单项内容,您可以执行以下操作(因为编码通过TextArea而遗漏了正确的泛型):
AddCommand = ReactiveCommand.Create();
AddCommand
.SelectMany(_ => DoSomethingAsync()
.Catch(ex => { log.write("Crap."); return Observable.Empty(); }))
.Subscribe(x => log.write("It worked!");