您必須撥打Subscribe
。
Rx中的查詢使用延遲評估,這意味着僅定義查詢不會啓動它。懶惰評估允許您通過有條件地應用運算符來構建查詢,只定義一次查詢並將其存儲在字段中供以後使用,或者在調用Subscribe
之前傳遞引用而不引起任何副作用。
沒有致電Subscribe
您的查詢將保持不活動狀態。
Subscribe
通過傳遞到您的觀察到激活IObserver<T>
查詢,也可以使用它的過載,使您可以單獨提供OnNext
,OnError
和/或OnCompleted
處理器,其中的Rx轉換爲IObserver<T>
你。接收查詢通知的是IObserver<T>
。
Subscribe
有一個無參數超載,它在內部使用無聲觀察者,目的是僅爲其副作用開始查詢。例如,在您的情況下,如果您要使用SelectMany
來完成加載建議的所有工作,並且您不需要單獨的IObserver<T>
,則可以通過調用Subscribe
的無參數超載來啓動查詢。
在大多數情況下,您不應使用Subscribe
的無參數超載。 Subscribe
的要點是,您傳遞給它的IObserver<T>
(或單個處理程序)旨在引起查詢的副作用。通過僅在Subscribe
或例如Do
運算符中產生副作用,查詢更易於推理和維護。
但是,有一個相當常見的場景,其中使用的Subscribe
的參數的過載是有道理的:如果查詢的副作用是通過異步方法造成的,那麼使用SelectMany
與Subscribe
的參超載一起是最好的。
原因很簡單:SelectMany
是順序組合運算符,它使您能夠將異步方法作爲查詢中的順序步驟調用。因此,SelectMany
將取消訂閱與取消異步計算綁定在一起。處理訂閱(由IDisposble
表示,由呼叫返回到Subscribe
)導致由SelectMany
運營商的特殊異步過載提供的CancellationToken
被標記爲取消。您的異步方法可以監視CancellationToken
以儘早退出其計算。
Subscribe
沒有任何接受異步觀察者的過載,OnNext
返回Task
。但即使您要在您的OnNext
處理程序中調用無返回異步方法,也不會在訂閱處理時發送異步方法。
請注意,無論如何,你的兩個代碼示例都有點不對。第一個示例不需要關鍵字async
和await
。如上所述,有特殊的過載SelectMany
接受一個Task<T>
返回選擇器功能,並提供一個CancellationToken
該功能的其他重載。你應該可以使用後者。
你的第二個例子不應該編譯,假設LoadSearchSuggestions
返回Task
。 (除非ReactiveUI庫或如果引用是提供接受Task
-returning功能Subscribe
過載一些其他圖書館,在這種情況下,你必須參考它們的文檔。)
除非後者,和假設您的查詢的其餘部分是正確的,這裏是你應該做的:
this.SearchTerms = this.ObservableForProperty(x => x.SearchTerm)
.Throttle(SuggestionThrottle, RxApp.MainThreadScheduler)
.Value()
.SelectMany(LoadSearchSuggestionsAsync)
.Subscribe();
其中LoadSearchSuggestionsAsync
這樣定義:
async Task<Unit> LoadSearchSuggestionsAsync(string term, CancellationToken cancel)
{
...
return Unit.Default;
}
注意Unit代表void in Rx。這是必需的,因爲返回非通用的異步方法Task
不能與SelectMany
一起使用。如果您有實際數據返回,則只需將Unit
替換爲您的數據類型即可。然後,您還可以將OnNext
處理程序傳遞給Subscribe
,並對返回值執行一些操作,如日誌記錄。
工程就像一個魅力。非常感謝您的詳細解答! – road242
這是我見過很長時間裏最好的Rx相關答案之一。謝謝你增加我的理解。 –