WCF ChannelFactory асинхронный вызов

Я играю с библиотекой WCF и TPL Async. Мне нужно иметь возможность запрашивать несколько методов WCF и ждать, пока все не будет завершено, так что я обнаружил, что в.NET 4.5 есть очень удобный метод Task.Factory.ContinueWhenAll, который может быть Подождал, пока все звонки не будут завершены

Я нашел следующие способы запроса вызова WCF в асинхронном режиме
Вариант 1. Использование прокси-сервера, созданного в диалоговом окне "Добавить ссылку" с опцией "Генерировать операции на основе задач" -> [например, здесь][1] - в моем случае не вариант, так как мы используем raw ChannelFactory
Вариант 2. Заворачивая синхронный вызов в задачу, например

    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
            }
        });

Вариант 3. Путем создания клиентской асинхронной версии контрактного интерфейса, например

[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);
}

И имея это, я могу вызвать метод асинхронно, например,

 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
                }
            });

Таким образом, вопрос заключается в следующем: какие преимущества имеет вариант 3 по сравнению с вариантом 2: правильно ли вызывать методы WCF, как в варианте 2? Вариант 2 имеет одно преимущество по сравнению с 3, а именно: нет необходимости создавать интерфейс контракта на стороне клиента.

1 ответ

В варианте № 2 каждый вызов GetData() будет блокировать поток на все время выполнения метода. В варианте № 3, пока GetDataAsync() операция в процессе, ни один поток не заблокирован этим.

Это означает, что вариант № 3 более эффективен, и вы должны использовать -Async вариант метода, если для вас важна эффективность.

Другие вопросы по тегам