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 text was updated successfully, but these errors were encountered:
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.
I have and Asp.Net app running 4.7.2. I want to start using async processing.
In case this helps others. We are running .NET 4.7 (hosted in Service Fabric) and using
But setting this does work:
Not sure what the different is or why there are two. Would be great if someone from @ms can explain.
@Jaans did you manage to work out the difference between the two keys? Does the "wcf:" key replace the "Switch" key?
Has anyone (@jcondex ?) had issues with OperationContext.Current occasionally returning null when completing an async call on a different thread? 99% of the time it works as expected (i.e. as per the 4.6.2 improvement) but the other 1% of the time returns null.
I've been hitting a brick wall on this for a few days now and am thinking of resorting to stashing OperationContext.Current before making an async call and if it's null after the call completes (on a different thread), then explicitly re-assign it. But this kind of defeats the purpose of the 4.6.2 ExecutionContext changes though.
why exactly do you "strongly encourage to use the default behavior of 4.7 and work around the
We have an issue in a custom endpoint behaviour that depends on OperationContext.Current but it when we call our external service async. I have added the following two settings to the configuration file of your WCF services project but unfortunaly this does not help in our case:
The work-around here is: