2017-01-25 78 views
0

我正在學習Rx.NET,並在下面的示例代碼中嘗試執行異步任務觀察日期時間選擇器值更改事件。 onNext運行完美,但onError和onComplete不。我究竟做錯了什麼?Rx.NET不會觸發onError也不onComplete

private void frmReporting_Load(object sender, EventArgs e){ 
    dtPickerValueChanged = Observable.FromEventPattern(
     ev => dtPickerFrom.ValueChanged += ev, 
     ev => dtPickerFrom.ValueChanged -= ev); 

    dtPickerValueChanged = dtPickerValueChanged.Merge(Observable.FromEventPattern(
     ev => dtPickerTo.ValueChanged += ev, 
     ev => dtPickerTo.ValueChanged -= ev)); 

    dtPickerValueChanged  
     .Where(x => dtPickerFrom.Value <= dtPickerTo.Value) 
     .Finally(() => { tsslStatus.Text = "Finally"; })  
     .ObserveOn(SynchronizationContext.Current) 
     .Subscribe(
      onNext: async x => { 
       var result = await Test(dtPickerFrom.Value, dtPickerTo.Value); 
       MessageBox.Show(result); 
      }, 
      onError: exception => { MessageBox.Show(exception.Message); }, 
      onCompleted:() => { MessageBox.Show("Finished loading data"); }); 
} 

public Task<string> Test(DateTime start, DateTime end){ 
    return Task.Run(
     async() => 
     { 
      await Task.Delay(3000); 
      return start.ToString("dd/MM/yyyy - HH:mm:ss") + " | " + end.ToString("dd/MM/yyyy - HH:mm:ss"); 
     }); 
} 
+0

你爲什麼期待'onError'或'onCompleted'射擊?沒有什麼是結束你的事件流或拋出錯誤。 – Jacob

+0

如果我在onNext中添加一個拋出的新Exception(「whatever」),它將無法在onErrror上捕獲它。關於完成我怎樣才能結束可觀察到的它不是一次性的?我見過很多教程和代碼示例,但我從來沒有找到有關何時調用每個動作的好解釋。 –

回答

0

當您不使用Rx並簡單地附加事件處理程序時,該事件無法告訴您它已完成。處理程序將假設即使只調用一次也會有更多事件(請考慮js land中的onLoaded事件)。將事件轉換爲可觀察對象時,您會看到相同的行爲; Rx庫無法知道事件流是否已結束。

您始終可以使用Take方法來限制訂戶收到的物品數量。希望這有助於回答爲什麼觀測永遠不會結束

MouseMove.TakeUntil(MouseUp).Subscribe(...); 
DocLoad.Take(1).Subscribe(...); 

至於使用onerror從來沒有被稱爲 - 如果你的用戶拋出一個錯誤,那麼這是你的用戶,而不是觀察到的自身問題,那就沒有什麼意義讓所有其他訂閱者知道一個子流氓。

OnError通常用於指示在序列中獲取值時發生錯誤。例如

Observable.Create(sub => { 
    try { 
     var res = SomethingThatCanThrow(); 
     sub.OnNext(res); 
     sub.OnCompleted(); 
    } catch (Exception ex) { 
     sub.OnError(ex); 
    } 

    return Disposable.Empty; 
});