My service using ConcurrencyMode.Multiple and my Framework code is identical to NET code.
NET code sometimes throws SFxCallbackRequestReplyInOrder1 exceptions in System.ServiceModel.Channels.ServiceChannel on client side.
While debugging my Framework code, I see that OperationContext.Current is always null and anyway ConcurrencyMode.Single, in NET code OperationContext.Current is not null and this results in an exception.
|
private void PrepareCall(ProxyOperationRuntime operation, bool oneway, ref ProxyRpc rpc) |
|
{ |
|
OperationContext context = OperationContext.Current; |
|
// Doing a request reply callback when dispatching in-order deadlocks. |
|
// We never receive the reply until we finish processing the current message. |
|
if (!oneway) |
|
{ |
|
DispatchRuntime dispatchBehavior = ClientRuntime.DispatchRuntime; |
|
if ((dispatchBehavior != null) && (dispatchBehavior.ConcurrencyMode == ConcurrencyMode.Single)) |
|
{ |
|
if ((context != null) && (!context.IsUserContext) && (context.InternalServiceChannel == this)) |
|
{ |
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.Format(SRP.SFxCallbackRequestReplyInOrder1, typeof(CallbackBehaviorAttribute).Name))); |
|
} |
|
} |
|
} |
This led me to this section of code where the OperationContext.Current value is assigned.
|
internal bool Process(bool isOperationContextSet) |
|
{ |
|
using (ServiceModelActivity.BoundOperation(Activity)) |
|
{ |
|
bool completed = true; |
|
|
|
if (NextProcessor != null) |
|
{ |
|
MessageRpcProcessor processor = NextProcessor; |
|
NextProcessor = null; |
|
|
|
OperationContext originalContext; |
|
if (!isOperationContextSet) |
|
{ |
|
originalContext = OperationContext.Current; |
|
} |
|
else |
|
{ |
|
originalContext = null; |
|
} |
|
IncrementBusyCount(); |
|
|
|
try |
|
{ |
|
if (!isOperationContextSet) |
|
{ |
|
OperationContext.Current = OperationContext; |
|
} |
|
|
|
processor(ref this); |
|
|
|
if (!IsPaused) |
|
{ |
|
OperationContext.SetClientReply(null, false); |
|
} |
|
} |
|
catch (Exception e) |
|
{ |
|
if (Fx.IsFatal(e)) |
|
{ |
|
throw; |
|
} |
|
if (!ProcessError(e) && FaultInfo.Fault == null) |
|
{ |
|
Abort(); |
|
} |
|
} |
|
finally |
|
{ |
|
try |
|
{ |
|
DecrementBusyCount(); |
|
|
|
if (!isOperationContextSet) |
|
{ |
|
OperationContext.Current = originalContext; |
|
} |
|
|
|
completed = !IsPaused; |
|
if (completed) |
|
{ |
|
channelHandler.DispatchDone(); |
|
OperationContext.ClearClientReplyNoThrow(); |
|
} |
|
} |
|
catch (Exception e) |
|
{ |
|
if (Fx.IsFatal(e)) |
|
{ |
|
throw; |
|
} |
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(e.Message, e); |
|
} |
|
} |
|
} |
|
|
|
return completed; |
|
} |
|
} |
I noticed that the Framework code uses
OperationContext.Holder instead of
OperationContext.Current
My service using
ConcurrencyMode.Multipleand my Framework code is identical to NET code.NET code sometimes throws
SFxCallbackRequestReplyInOrder1exceptions inSystem.ServiceModel.Channels.ServiceChannelon client side.While debugging my Framework code, I see that
OperationContext.Currentis always null and anywayConcurrencyMode.Single, in NET codeOperationContext.Currentis not null and this results in an exception.wcf/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/ServiceChannel.cs
Lines 526 to 541 in 9bd5ad4
This led me to this section of code where the
OperationContext.Currentvalue is assigned.wcf/src/System.ServiceModel.Primitives/src/System/ServiceModel/Dispatcher/MessageRpc.cs
Lines 397 to 475 in 9bd5ad4
I noticed that the Framework code uses
OperationContext.Holderinstead ofOperationContext.Current