Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
wcf:disableOperationContextAsyncFlow flag set to true by default #403
Our application has been working fine until we upgraded to .NET 4.7. Now it appears that the OperationContext.Current is null after performing async/await calls.
The OperationContext.Current continues to be set properly on .NET 4.6.2 and lower, just not on machines that do not have .NET 4.7 installed.
I see in ServiceModelAppSettings that
DefaultDisableOperationContextAsyncFlow = true;
Is this this a breaking change in .NET 4.7?
BTW, my guess is that this is something developers would want to opt out of, not in.
The default value of the appSettings switch is correct and it is indeed a breaking change. I strongly encourage you to use the default behavior of 4.7 and work around the OperationContext.Current being null after an async/await call by doing something like this:
public async Task Test()
In .NET 4.6.2 we added support for WCF’s OperationContext.Current to correctly flow with the ExecutionContext in asynchronous continuations.
Previously, the internal implementation of OperationContext.Current was to store the Current context using a ThreadStatic variable, which used the thread's local storage (TLS) to store the data associated with Current context. The problem with this is if there was a change in the execution context of the method call (i.e. a thread change caused by awaiting another operation), any subsequent calls to OperationContext.Current would result in null being returned. The way we implemented the feature was to rely on AsyncLocal to provide the persisting the value of the OperationContext across different threads.
There are currently are two known issues around this feature that break old scenarios.
Issue #1: Users might obtain a NULL result when calling OperationContext.Current
This issue occurs when one creates an OperationContextScope and proceeds to call OperationContext.Current within the using clause. A common pattern that is prone to this failure is the following:
using (new OperationContextScope(OperationContext.Current))
To work around this issue, one needs to change the code to something similar to the following:
OperationContext ocx = OperationContext.Current;
Issue #2: Users might run into a deadlock when using Reentrant services.
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
To work around this issue, users should set the ConcurrencyMode of their service to ConcurrencyMode.Single or ConcurrencyMode.Multiple, and provide the appropriate synchronization primitives to ensure a single thread can execute a single method at a time.
We have rolled out an update of System.ServiceModel.dll and we strongly encourage users to patch their existing .NET 4.6.2 framework. The patch fixes Issue #1, disables the flow of OperationContext.Current by default, and provides an Opt-In option to enables feature.
To enable the flow of OperationContext.Current across multiple threads in async operations, use the following AppSettings key:
Setting the value of Switch.System.ServiceModel.DisableOperationContextAsyncFlow to true will disable the flow of the ExecutionContext in OperationContext.Current and will effectively revert the behavior to pre-4.6.2, which is the default behavior after this patch. Setting the value to false will enable the feature and should not be used in Reentrant services.
Thank you for the information jcondex.
We will just have to be careful with our customers that are currently running our product on .NET 4.6.2 because if they upgrade to 4.7 without first upgrading our product, it will fail with NREs due to this change.
We do not use ConcurrencyMode.Reentrant, so we should be good setting disableOperationContextAsyncFlow to false in the App.config.