goo*_*nd0 0 c# concurrency system.reactive
我正在尝试在新线程上安排一个可观察对象,并将结果返回到当前线程上。
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我得到的结果:
init on 9
Do1 method on 10
Do2 method on 10
subscribe method on 10
Run Code Online (Sandbox Code Playgroud)
为什么 Do2 方法和 subscribe 方法在线程 #10 上而不是在线程 #9 上?我期待这个结果:
init on 9
Do1 method on 10
Do2 method on 9
subscribe method on 9
Run Code Online (Sandbox Code Playgroud)
我可以看到您想要实现的目标,但这可能会很困难,因为您只是在同步线程上的控制台应用程序中运行。由于主控制台线程不是 EventLoop,Rx 如何能够“解锁”调用Console.ReadKey()、劫持线程执行Log方法,然后返回等待Console.ReadKey()?
如果您在 GUI 应用程序中执行此操作,那么主线程将是某种 EventLoop,即 WPF/Silverlight 中的 Dispatcher。现在可以轻松地将控制权返回到“主线程” -ObserveOn(_dispatcherScheduler)捕获_dispatcherScheduler的DispatcherScheduler.
您可以在此处查看Immediate和CurrentSchedulers 的说明 - http://introtorx.com/Content/v1.0.10621.0/15_SchedulingAndThreading.html#SchedulersIndepth。
原始代码的替代方案可能是运行第三个线程来充当 EventLoop,使用完美命名的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);
}
Run Code Online (Sandbox Code Playgroud)
这会创建以下(预期)输出
init on 28
Do1 method on 29
Do2 method on 28
subscribe method on 28
Run Code Online (Sandbox Code Playgroud)