7

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.

Krzysiek
  • 328
  • 2
  • 10
  • 1
    If you're on .Net 4.5, why aren't you using `async`-`await`? – svick Jun 23 '13 at 18:41
  • Maybe I am doing something wrong but when I tried execute two calls using asyns e.g. var t1 = await factory.CreateChannel().GetDataAsync(2); var t2 = await factory.CreateChannel().GetDataAsync(5); and each call was asynchronous but they were not performed simultaniously -> second request started after first was finished. – Krzysiek Jun 23 '13 at 18:58
  • Well, that's because `await` doesn't change the order of execution. You need to call the first method and store its `Task`, call the second method and store its `Task` and only then `await` both. – svick Jun 23 '13 at 19:02
  • I knew that there have to be a way to mitigate this issue with async mentioned by me previousy, thanks. But the main question is still open, which option is better ? – Krzysiek Jun 23 '13 at 19:18

1 Answers1

4

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.

svick
  • 236,525
  • 50
  • 385
  • 514
  • Hi svick, I have a similar issue and was wondering if you could share the `async` equivalent. I am calling from a synchronous method but want to call multiple WCF services asynchronously. SO: https://stackoverflow.com/q/57572902/919426. If you answer with a sample for this question and an alternative that addresses my SO question, I will award you the bounty :) – tinonetic Aug 20 '19 at 15:16