2014-10-18 56 views
1

我目前正在使用ReactiveUI(在使用Rx之前有过一些经验)。 我想要做的是处理某种形式的火灾/遗忘/通知工作流程。使用ReactiveUI进行扫描并忘记

基本上,我想要执行和操作,然后在成功或失败时通知。不过,我不想等待行动做下一个之前完成,所以我实现下面的代码片段:

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); 
    } 

此代码的工作,我希望它。我可以根据需要多次调用该命令,并立即通知该命令已被调用,然后1秒后通知该命令已完成。

我有一种感觉,虽然,通过使用ReactiveCommand和主题,我可能会丢失ReactiveUI的地步?另外,通过使用这个主题,我没有得到直接使用ReactiveCommands获得的那个可爱的ThrownError观察值。

对于背景下,UI包含两个列表和一个按钮,点击按钮从一个列表移动的到另一个字符串,一秒钟后,该字符串与“验证”标志更新。

编辑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这样我就可以取消这些东西......

我错过了一些东西明显?

回答

1

如果你想退出RxCmd的单item'ing的,你做这样的事情(左,因为适当的仿制药编码,通过-文本区域):

AddCommand = ReactiveCommand.Create(); 

AddCommand 
    .SelectMany(_ => DoSomethingAsync() 
     .Catch(ex => { log.write("Crap."); return Observable.Empty(); })) 
    .Subscribe(x => log.write("It worked!");