Understanding Reactive Extensions and CallContext

I have code that uses CallContext to pass session information throughout a task. Now I introduced the use of Reactive Extensions, and I am observing some strange behavior that I would like to understand.

I have this helper class that wraps using 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); } } } 

In my main function, I create a cold observable interval. At each tick, I project the context value to see what context is present in the pipeline.

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

In a loop, I set the context to the loop index, and then subscribe and unload the sequence using the LINQPad DumpLatest method. For fun, I set the context to a different value (42) at the end of the iteration.

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

I expect each subscription to capture context from the time of the subscription. I expect subscription notifications to match the iteration number of the subscription.

This works exactly as expected when my scheduler is Scheduler.Default, as mentioned above.

With Scheduler.Default

However, if I change the scheduler to new EventLoopScheduler() , all subscriptions will use the same context.

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

With EventLoopScheduler

Why is Scheduler.Default distributing CallContext as I expect while EventLoopScheduler is not working?

Thanks Ranj

+5
source share

All Articles