我正在尝试在新线程上安排一个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方法和subscribe方法在#10号线而不是#9?我期待这个结果:
init on 9
Do1 method on 10
Do2 method on 9
subscribe method on 9
答案 0 :(得分:3)
我可以看到你想要实现的目标,但这可能很难,因为你只是在同步线程的控制台应用程序中运行。
由于主控制台线程不是EventLoop,Rx如何能够“解锁”" Console.ReadKey()
调用,劫持线程执行Log
方法,然后返回等待Console.ReadKey()
?
如果您在GUI应用程序中执行此操作,则主线程将是某种EventLoop,即WPF / Silverlight中的Dispatcher。
现在很容易将控制返回到主线程" - ObserveOn(_dispatcherScheduler)
其中_dispatcherScheduler
是DispatcherScheduler
的捕获实例。
您可以在此处查看Immediate
和Current
计划程序的解释 - 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