我有使用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); }
}
}
在我的main函数中,我使用interval创建一个cold observable。在每个刻度上,我投影上下文值以查看管道中存在的上下文。
var periodic = Observable.Interval(TimeSpan.FromMilliseconds(100), Scheduler.Default)
.Select(_ => TestContext.Value)
.Timestamp();
在循环中,我将上下文设置为循环索引,然后使用LINQPad的DumpLatest方法订阅并转储序列。为了好玩,我在迭代结束时将上下文设置为不同的值(42)。
for (int i = 0; i < 3; i++)
{
TestContext.Value = i;
periodic
.DumpLatest(string.Format("Iteration {0}", i));
TestContext.Value = 42;
}
我希望每个订阅都能从订阅时间捕获上下文。我希望订阅通知与订阅迭代号匹配。
当我的调度程序是Scheduler.Default时,这完全符合预期,如上面编码的那样。
但是,如果我将调度程序更改为new EventLoopScheduler()
,则所有订阅都使用相同的上下文。
var periodic = Observable.Interval(TimeSpan.FromMilliseconds(100), new EventLoopScheduler())
.Select(_ => TestContext.Value)
.Timestamp();
为什么Scheduler.Default会按照我的预期传播CallContext,而EventLoopScheduler却没有?
谢谢, Ranj