2016-06-16 101 views
0

我想在新線程上安排一個observable,並在當前線程上得到結果。觀察回當前線程

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Log("init"); 

      Observable.Return(0) 
       .ObserveOn(NewThreadScheduler.Default) 
       .Do(_ => Log("Do1 method")) 
       .ObserveOn(CurrentThreadScheduler.Instance) 
       .Do(_ => Log("Do2 method")) 
       .Subscribe(_ => Log("subscribe method")); 

      Console.ReadKey(); 
     } 

     static void Log(string label) 
     { 
      Console.WriteLine("{0} on {1}", label, Thread.CurrentThread.ManagedThreadId); 
     } 
    } 
} 

這是結果我得到:

init on 9 
Do1 method on 10 
Do2 method on 10 
subscribe method on 10 

爲什麼DO2方法和訂閱方法上線#10,而不是9號?我期待這樣的結果:

init on 9 
Do1 method on 10 
Do2 method on 9 
subscribe method on 9 

回答

2

我可以看到你想要達到的,但是這可能證明是困難的,因爲你只是在一個控制檯應用程序運行在同步線程。 由於主控臺線程不是EventLoop,Rx如何​​才能夠「解鎖」Console.ReadKey()調用,劫持線程執行Log方法,然後返回等待到Console.ReadKey()

如果您是在GUI應用程序中執行此操作,那麼主線程將是某種EventLoop,即WPF/Silverlight中的Dispatcher。 這現在很容易將控制返回到「主線程」 - ObserveOn(_dispatcherScheduler)其中_dispatcherSchedulerDispatcherScheduler的捕獲實例。

你可以在這裏看到解釋ImmediateCurrent排程器 - http://introtorx.com/Content/v1.0.10621.0/15_SchedulingAndThreading.html#SchedulersIndepth

到您的原代碼的替代可能是跑第三線程使用完全名爲EventLoopScheduler

void Main() 
{ 
    var els = new EventLoopScheduler(ts => new Thread(ts) { IsBackground = true, Name = "MyEventLoopThread"}); 
    els.Schedule(0, (scheduler, _)=>Run(scheduler)); 
} 
static IDisposable Run(IScheduler mainThreadScheduler) 
{ 
    Log("init"); 
    return Observable.Return(0) 
     .ObserveOn(NewThreadScheduler.Default) 
     .Do(_ => Log("Do1 method")) 
     .ObserveOn(mainThreadScheduler) 
     .Do(_ => Log("Do2 method")) 
     .Subscribe(_ => Log("subscribe method")); 
} 
static void Log(string label) 
{ 
    Console.WriteLine("{0} on {1}", label, Thread.CurrentThread.ManagedThreadId); 
} 

它創建以下(預期)輸出

init on 28 
Do1 method on 29 
Do2 method on 28 
subscribe method on 28 
+0

感謝的事件循環行事很多!我的應用程序工作正常,但我沒有在控制檯項目中重現它。 – goodfriend0