WCF Proxy Abort that did not cache ChannelFactory with CancellationToken causes deadlock

So how is it.

There is a WCF service. I created a proxy for it using "Add Service Reference" with task based operations.

The endpoint address for this service can change for different users. I have no control over this service, the provider just does it this way.

Then I migrate this service to another type and through this interaction with the WCF service.

Everything looks like this:

//Generated code
public partial class MyServiceClient: System.ServiceModel.ClientBase<IMyService>, IMyService
{
   public async Task<ResultDataContractType> GetResultsAsync(ArgsDataContractType args)
   {
      return base.Channel.GetResultsAsync(args); 
   }
}

...
...
...
//end of generated code

public class ClientFactory
{
   public static IMyService CreateClient(string url)
   {
      var binding = new BasicHttpBinding();
      var address = new EndpointAddress(url);
      var client = new MyServiceClient(binding, address);
      return client;
   }
}

public class Wrapper()
{
    public async Task<ResultType> GetResultsAsync(string url, ArgsType args, CancelationToke cancelationToken)
    {
        var client = ClientFactory.CreateClient(url);

        try
        {
            cancellationToken.Register(target =>
            {
                var communicationObject = target as ICommunicationObject;
                if (communicationObject != null)
                {
                    communicationObject.Abort();
                }
            }, client);

            ArgsDataContractType requestArgs = MapArgs(args);

            ResultDataContractType result = await client.GetResultsAsync(args);
       }
    }
}


public class Consumer
{
   public async void DoWork()
   {
      var args = new ArgsType 
      {
         ...
      };

      var cts = new CancellationTokenSource()

      var wrapper = new Wrapper();

      Task<ResultType> task = wrapper.GetResultsAsync("http://someaddress.com", args, cts.Token);

      cts.Cancel(); //This is made intentionaly, normaly there is timeout timespan for token source

      await task;

      ... 
      ...
      ...

   }
}

      

Consumer

is actually a NUnit unit test, but calling the same code from an ASP.NET application will end up deadlocked as well. It gets stuck onawait task;

What I noticed is that if I installed MyServiceClient.CacheSetting = CacheSetting.AlwaysOn;

this code would work without blocking.

Also, if I configured MyServiceClient

from App.config or Web.config would make the code run without blocking. But if I set MyServiceClient.CacheSetting = CacheSetting.AlwaysOff;

before instantiating MyServiceClient

, this code gets stuck.

Also, setting up awaiter like this:

ResultDataContractType result = await client.GetResultsAsync(args).ConfigureAwait(false)

      

Runs code without blocking.

Could you please give me any idea as to why this deadlock doesn't happen when ChannelFactory

for is MyServiceClient

cached and happens if it is not cached?

+3


source to share





All Articles