Say, I have the following code:
IPrincipal capturedPrincipal = Thread.CurrentPrincipal;
myseq.AsParallel().Select(x =>
{
Thread.CurrenctPrincipal = capturedPrincipal;
/*call code protected with CAS*/
});
to be sure Thread.CurrenctPrincipal
will be propagated to every thread where Select
's delegate will be executed on. I've realized that if I had proper SynchronizationContext
set up this would happen automatically. So does PLINQ use SynchronizationContext
when queuing work items on ThreadPool
? And if no, why?
p.s.
I think it's important to note that the code above is executed in WCF environment hosted under IIS/WAS (no ASP.NET compatibility).
Edit: Found a similar question confirming same behavior I witness.
Edit2: Modified casperOne's test a bit and it fails saying threadid is the same:
[Test]
public void Test1()
{
var principal = new GenericPrincipal(new GenericIdentity("test"), new string[0]);
Thread.CurrentPrincipal = principal;
int threadID = Thread.CurrentThread.ManagedThreadId;
Enumerable.Range(0, 4000).AsParallel()
.WithExecutionMode(ParallelExecutionMode.ForceParallelism)
.Select(x =>
{
Assert.AreSame(Thread.CurrentPrincipal, principal);
Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, threadID);
return x;
})
.ToArray();
}
There are two questions here. The first is whether or not
Thread.CurrentPrincipal
is propagated to threads in PLINQ.The answer is yes, as this is part of the
ExecutionContext
and the ExecutionContext is captured from the calling thread and copied to the new/recycled thread when a new thread/task/thread pool thread is started.The following test case (run in .NET 4.0) shows this:
Regarding whether or not
SynchronizationContext
is used in PLINQ, it's not, and it doesn't make sense to.Considering that using a
SynchronizationContext
usually means serializing a call to a particular context (which is usually a thread, think UI applications, but not always, given the ASP.NET synchronization context), you'd kill any gains that PLINQ would gain from parallelization because every call would have to be marshaled back through theSynchronizationContext
.The benefits in PLINQ come from being able to execute these operations at the same time, not one-at-a-time.
The following test case (very much along the lines of the previous one) proves that the
SynchronizationContext
is not captured for PLINQ threads: