diff --git a/src/System.Private.ServiceModel/tests/Common/Scenarios/ServiceInterfaces.cs b/src/System.Private.ServiceModel/tests/Common/Scenarios/ServiceInterfaces.cs index 0ce1e7ffc4f..2a7909590f4 100644 --- a/src/System.Private.ServiceModel/tests/Common/Scenarios/ServiceInterfaces.cs +++ b/src/System.Private.ServiceModel/tests/Common/Scenarios/ServiceInterfaces.cs @@ -89,6 +89,9 @@ public interface IWcfService [OperationContract] Dictionary GetRequestHttpHeaders(); + + [OperationContract] + Task EchoReturnTaskAsync(); } [ServiceContract] diff --git a/src/System.Private.ServiceModel/tests/Scenarios/Binding/Tcp/NetTcpBindingTests.4.0.0.cs b/src/System.Private.ServiceModel/tests/Scenarios/Binding/Tcp/NetTcpBindingTests.4.0.0.cs index f146d518fe0..9b2920d2e0f 100644 --- a/src/System.Private.ServiceModel/tests/Scenarios/Binding/Tcp/NetTcpBindingTests.4.0.0.cs +++ b/src/System.Private.ServiceModel/tests/Scenarios/Binding/Tcp/NetTcpBindingTests.4.0.0.cs @@ -82,6 +82,45 @@ public static async Task SecurityModeNone_Echo_RoundTrips_String_SyncAfterAsync( } } + // Test for https://github.com/dotnet/wcf/issues/5626 + [WcfFact] + [OuterLoop] + public static async Task SecurityModeNone_Echo_RoundTrips_Task_SyncAfterAsync() + { + string testString = "Hello"; + ChannelFactory factory = null; + IWcfService serviceProxy = null; + + try + { + // *** SETUP *** \\ + NetTcpBinding binding = new NetTcpBinding(SecurityMode.None); + factory = new ChannelFactory(binding, new EndpointAddress(Endpoints.Tcp_NoSecurity_Address)); + serviceProxy = factory.CreateChannel(); + + // *** EXECUTE *** \\ + string result = serviceProxy.Echo(testString); + Assert.Equal(testString, result); + + // Without the ConfigureAwait, the xunit sync context will hop threads from the + // completing thread to their sync context. ConfigureAwait means it continues + // executing on the completing thread and triggers the bug (without the fix). + await serviceProxy.EchoReturnTaskAsync().ConfigureAwait(false); + + result = serviceProxy.Echo(testString); + Assert.Equal(testString, result); + + // *** CLEANUP *** \\ + ((ICommunicationObject)serviceProxy).Close(); + factory.Close(); + } + finally + { + // *** ENSURE CLEANUP *** \\ + ScenarioTestHelpers.CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory); + } + } + // Test for https://github.com/dotnet/wcf/issues/5134 [WcfFact] [OuterLoop] diff --git a/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/IWcfService.cs b/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/IWcfService.cs index d8abb1bf1d6..ccb45318c61 100644 --- a/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/IWcfService.cs +++ b/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/IWcfService.cs @@ -160,5 +160,8 @@ public interface IWcfService [OperationContract] Dictionary GetRequestHttpHeaders(); + + [OperationContract] + System.Threading.Tasks.Task EchoReturnTask(); } } diff --git a/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/WcfService.cs b/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/WcfService.cs index 1cd313715bf..dc233de69ac 100644 --- a/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/WcfService.cs +++ b/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/WcfService.cs @@ -468,5 +468,13 @@ private static Stream StringToStream(string str) return ms; } + + public System.Threading.Tasks.Task EchoReturnTask() + { + return System.Threading.Tasks.Task.Run(() => + { + System.Threading.Tasks.Task.Delay(1).Wait(); + }); + } } } diff --git a/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/ServiceChannelProxy.cs b/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/ServiceChannelProxy.cs index 10d0aec6253..4c7254ca8a6 100644 --- a/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/ServiceChannelProxy.cs +++ b/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/ServiceChannelProxy.cs @@ -210,7 +210,7 @@ private static Task CreateGenericTask(ServiceChannel channel, ProxyOperationRunt private static Task CreateTask(ServiceChannel channel, ProxyOperationRuntime operation, object[] inputParameters) { - TaskCompletionSource tcs = new TaskCompletionSource(); + TaskCompletionSource tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); bool completedCallback = false; Action endCallDelegate = (asyncResult) =>