2011-08-15 75 views
8

我有一個類來創建一個可觀察的包裝,對於非線程安全類

public class Test 
{ 
    public int Calc(); 
} 

這要求在同一個線程上測試創建一個上執行Calc的所有呼叫。我需要創建一次測試(昂貴的操作),並多次調用Calc。

我想有一個包裝,將讓我asynchronousely調用計算:

public class TestWrapper 
{ 
    private Test _test; 
    public IObservable<int> Calc(); 
} 

一種方式做到這一點是創建一個BackgroundWorker或線程,並用它作爲保證所有操作在測試上是在同一個線程上。爲了簡單起見,我們可以假設所有對Calc()的調用都將按順序執行,所以不必擔心排隊。

有沒有更優雅的RX方式來做到這一點?

回答

4

如果這是可能的,當創建TestWrapperTest要創建那麼這個類似乎滿足您的要求:

public class TestWrapper 
{ 
    public TestWrapper(Func<Test> factory) 
    { 
     _scheduler = new EventLoopScheduler(); 
     _test = Observable.Start(factory, _scheduler).First(); 
    } 

    private readonly EventLoopScheduler _scheduler; 
    private readonly Test _test; 

    public IObservable<int> Calc() 
    { 
     return Observable.Start(() => _test.Calc(), _scheduler); 
    } 
} 

它用於像這樣:

var testWrapper = new TestWrapper(() => new Test()); 
testWrapper.Calc().Subscribe(x => { }); 

我已經對它進行了測試,並在執行Calc的同一線程上創建了Test。另一方面,訂閱在與創建本身(即調用線程)上的testWrapper相同的線程上處理。

3

因此,從評論和重新讀你的問題我收集你想反覆調用Calc()在一個恆定的線程,並有返回結果可用IObservable<Int>()

在這種情況下,我會使用Observable.Create來包裝Test類和EventLoopScheduler以確保Calc的調用位於單個線程上。

public class TestWrapper 
{ 
    private Test _test; 
    public IObservable<int> Calc() 
    { 
    return Observable.Create(obsvr => 
    { 
     var fixedThreadsched = new EventLoopScheduler(); 
     var disp = new BooleanDisposable(); 
     while (!disp.IsDisposed) 
     { 
      fixedThreadsched.Schedule(() => obsvr.OnNext(_test.Calc())); 
     } 

     return disp; 
    }); 
    } 
} 
+0

謝謝,EventLoopScheduler是封送到同一個線程的調用的關鍵。儘管如此,這個答案並沒有解釋如何從TestWrapper.Calc切換到UI,在線程上執行test.Calc ... –

+0

@Sergey - 根據你的意見更新 –

+0

這是更接近...缺少的是你不要創建_test(這應該在EventLoopScheduler上完成)。嗯...很難決定 - 你是第一個使用EventLoopScheduler,但是@enigmativity提供了正確的答案。謝謝你們,你們都搖滾! –