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
вариант метода, если для вас важна эффективность.