爲了讓熱的可觀的,我可能會與使用BehaviorSubject
作爲返回值和操作報告進度的方式方法入手。如果你只是想要這個例子,跳到最後。這個答案的其餘部分解釋了這些步驟。
爲了這個答案,我會假設你的長時間運行沒有自己的方法來異步調用。如果他們這樣做,下一步可能會有所不同。接下來要做的工作是使用IScheduler
將工作發送到另一個線程。如果需要,您可以允許調用者選擇將工作調度器作爲參數的過載(在這種情況下,過載不會選擇默認調度器),從而選擇工作發生的位置。 IScheduler.Scheduler
有很多重載,其中有幾個是擴展方法,所以你應該通過它們來查看哪些最適合你的情況。我在這裏只用了Action
。如果您有多個可以並行運行的操作,則可以多次撥打scheduler.Schedule
。
其中最難的部分可能是確定在任何給定點上的進展。如果您有多個操作同時進行,那麼您可能需要跟蹤已完成的操作數,以瞭解當前的進度。根據你提供的信息,我不能比這更具體。
最後,如果您的操作可以取消,您可能需要將CancellationToken
作爲參數。在啓動之前,您可以使用它來取消調度程序隊列中的操作。如果您正確編寫操作代碼,它也可以使用令牌進行取消。
IObservable<int> DoStuff(/*args*/,
CancellationToken cancel,
IScheduler scheduler)
{
BehaviorSubject<int> progress;
//if you don't take it as a parameter, pick a scheduler
//IScheduler scheduler = Scheduler.ThreadPool;
var disp = scheduler.Schedule(() =>
{
//do stuff that needs to run on another thread
//report progres
porgress.OnNext(25);
});
var disp2 = scheduler.Schedule(...);
//if the operation is cancelled before the scheduler has started it,
//you need to dispose the return from the Schedule calls
var allOps = new CompositeDisposable(disp, disp2);
cancel.Register(allOps.Dispose);
return progress;
}
這是一個很好的示例和解釋。謝謝。我只有一個問題。如果我的長時間運行的操作被分成幾組,並且我需要在並行執行組內操作的同時連續執行組?我應該在這種情況下使用任務庫,允許通過ContinueWith而不是調度器鏈接這種類型,但保留使用BehaviorSubject? – andriys 2012-01-04 13:30:04
@andriys這是一個選項。另一種選擇是將每個組劃分爲一個返回IObservable的單獨函數。這些函數可以通過'Observable.Concat'鏈接在一起。但是,你會希望除了鏈條中的第一個可觀察對象之外的其他所有元素都變冷。 '觀察到。Defer'可以讓你將一個熱門的觀察者轉換成一個冷的觀察者。 – 2012-01-04 14:00:15
太好了,謝謝你的指導! – andriys 2012-01-04 15:15:33