Synchron calls after Asynchron calls with no result blocks forever
Describe the bug When I call a sync WCF OperatinContract after an async OperationContract call with no result the synchron call is never resolved. If the perverious async call has a result this problem does not happen.
To Reproduce Create a WCF Service with Async Methods that returns somsthing (Test1Async) and one that returns nothing (Test2Async) and add a sync Method (Test3)
[ServiceContract]
public interface ITestService
{
[OperationContract]
Task<string> Test1Async(string text);
[OperationContract]
Task Test2Async(string text);
[OperationContract]
string Test3(string text);
}
Call the WCF Interface (see code below with comments)
private static async Task CallNetPipeBinding(string hostAddr)
{
IClientChannel channel = null;
var binding = new NetNamedPipeBinding();
var factory = new ChannelFactory<ITestService>(binding, new EndpointAddress($"{hostAddr}/netPipe"));
await Task.Factory.FromAsync(factory.BeginOpen, factory.EndOpen, TaskCreationOptions.None);
try
{
ITestService client = factory.CreateChannel();
channel = client as IClientChannel;
await Task.Factory.FromAsync(channel.BeginOpen, channel.EndOpen, TaskCreationOptions.None);
await client.Test1Async("Test");
client.Test3("Test");// This call works because the perverious call returns something
await client.Test2Async("Test");
client.Test3("Test");// This call does not work becausee the pereverious call returns nothing
}
finally
{
factory.Close();
}
}
Expected behavior Synchron calls after async call with no result don't block forever.
Additional context
I think the problem is that the TaskCompletionSource withtout result is not created with TaskCreationOptions.RunContinuationsAsynchronously
TaskCompletionSource Creation with return Type: https://github.com/dotnet/wcf/blob/c7b4036b7f103d60df2b3fad4d5f8a74f2adfad4/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/ServiceChannelProxy.cs#L318
https://github.com/dotnet/wcf/blob/c7b4036b7f103d60df2b3fad4d5f8a74f2adfad4/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/ServiceChannelProxy.cs#L174
TaskCompletionSource Creation without return Type: https://github.com/dotnet/wcf/blob/c7b4036b7f103d60df2b3fad4d5f8a74f2adfad4/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/ServiceChannelProxy.cs#L213
Which package version are you using? I believe this was fixed in the last year or two.
I believe this is the explanation of what's going on along with a workaround if you can't upgrade to a fixed version.
https://github.com/dotnet/wcf/issues/4946#issuecomment-1472715803
Basically you do this:
await client.Test1Async("Test");
client.Test3("Test");// This call works because the perverious call returns something
await client.Test2Async("Test");
await Task.Yield();
client.Test3("Test");// This call does not work becausee the pereverious call returns nothing
I tested it with the NuGet Packages Version 8.0.0 and with a local build of the master branch witch is less then a month old.
The Example in https://github.com/dotnet/wcf/issues/4946#issuecomment-1472715803 only uses Tasks with a result Task<T> and this works without any problems for me. But if my Task does not have a result Task is doesn't work.
@imcarolwang can you please create a PR and add unit tests for this?