WCF ChannelFactory asynchronous call

2020-02-05 04:40发布

问题:

I am playing with WCF and TPL Async library What I need is to be able request multiple WCF methods and wait untill all will be finished, so far I found that in .NET 4.5 there is very handy method Task.Factory.ContinueWhenAll which can be used to wait until all calls are finished

I found folowing ways to request WCF call in asynchronous way
Option 1. By using a proxy generated by "Add reference" dialog with option "Generate task-based operations" -> [e.g. here][1] - not an option in my case as we are using raw ChannelFactory
Option 2. By wrapping synchronous call in a task e.g.

    ChannelFactory<IService1> factory = new ChannelFactory<IService1>("BasicHttpBinding_IService1");  

        Task<string> t1 = Task<string>.Factory.StartNew(() => { return factory.CreateChannel().GetData(2); });
        Task<string> t2 = Task<string>.Factory.StartNew(() => { return factory.CreateChannel().GetData(5); });

        Task.Factory.ContinueWhenAll(new[] { t1, t2 }, t =>
        {
            foreach (var task in t)
            {
                //get result here
            }
        });

Option 3. By creating client side asynchronous version of contract interface e.g.

[ServiceContract(Namespace = "X", Name = "TheContract")]//Server side contract
public interface IService1
{
    [OperationContract]
    string GetData(int value);
}

[ServiceContract(Namespace = "X", Name = "TheContract")]//client side contract
public interface IService1Async
{
    [OperationContract]
    string GetData(int value);

    [OperationContract]
    Task<string> GetDataAsync(int value);
}

And having this I can invoke method asynchronously e.g.

 ChannelFactory<IService1Async> factory = new ChannelFactory<IService1Async>("BasicHttpBinding_IService2");

        var t1 = factory.CreateChannel().GetDataAsync(2);
        var t2 = factory.CreateChannel().GetDataAsync(5);

        Task.Factory.ContinueWhenAll(new[] { t1, t2 }, (Task<string>[] t) =>
            {
                foreach (var task in t)
                {
                    //get result here
                }
            });

So the question is as follows, what advantages has option 3 in comparison with option 2, is calling WCF methods as in Option 2 is correct ? Option 2 has one advantages in comparison with 3 namely there is no need to create client side contract interface.

回答1:

In option #2, each invocation of GetData() will block a thread for the whole time the method executes. In option #3, while the GetDataAsync() operation is in progress, no thread is blocked by it.

This means that option #3 is more efficient and you should use the -Async version of the method if efficiency is important for you.