了解Reactive Extensions和CallContext

Ran*_*anj 5 .net system.reactive

我有使用CallContext将会话信息传输到任务延续的代码.现在我已经介绍了Reactive Extensions的使用,我正在观察一些我想要了解的奇怪行为.

我有这个包含CallContext使用的帮助器类.

public static class TestContext
{
    private static readonly string _KEY = "my-context";

    public static int Value
    {
        get { return CallContext.LogicalGetData(_KEY) as int? ?? -1; }
        set { CallContext.LogicalSetData(_KEY, value); }
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的main函数中,我使用interval创建了一个cold observable.在每个tick上,我投影上下文值以查看管道中存在的上下文.

var periodic = Observable.Interval(TimeSpan.FromMilliseconds(100), Scheduler.Default)
    .Select(_ => TestContext.Value)
    .Timestamp();
Run Code Online (Sandbox Code Playgroud)

在循环中,我将上下文设置为循环索引,然后使用LINQPad的DumpLatest方法订阅并转储序列.为了好玩,我在迭代结束时将上下文设置为不同的值(42).

for (int i = 0; i < 3; i++)
{
    TestContext.Value = i;
    periodic
        .DumpLatest(string.Format("Iteration {0}", i));
    TestContext.Value = 42;
}
Run Code Online (Sandbox Code Playgroud)

我希望每个订阅从订阅时间捕获上下文.我希望订阅通知与订阅迭代次数匹配.

当我的调度程序是Scheduler.Default时,这完全符合预期,如上面编码的那样.

使用Scheduler.Default

但是,如果我将调度程序更改为new EventLoopScheduler()所有订阅,请使用相同的上下文.

var periodic = Observable.Interval(TimeSpan.FromMilliseconds(100), new EventLoopScheduler())
    .Select(_ => TestContext.Value)
    .Timestamp();
Run Code Online (Sandbox Code Playgroud)

使用EventLoopScheduler

为什么Scheduler.Default会像我期望的那样传播CallContext,而EventLoopScheduler却没有?

谢谢,Ranj