Разница между применением асинхронного ожидания на клиенте и на службе

Я создал службу WCF и имею ее операционный контракт и реализацию следующим образом:

    [OperationContract]
    Task<string> GetName(string name);

   public async Task<string> GetName(string name)
    {
         await Task.Delay(5000);
         var task1 = Task<string>.Factory.StartNew(() =>
         {
             return "Your name is : " + name;
         });
         var result = await task1;
         return result;
        }

Теперь я использую этот сервис на стороне клиента и создал клиент.

 ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();

Для моей реализации показано 2 метода: GetName и GetNameAsync.

Я могу использовать следующие два способа доступа к сервису.

var result_GetName = await Task.Factory.StartNew(() => client.GetName("My Input"));
 var result_GetNameAsync = await client.GetNameAsync("My Input");
  • В.1 Есть ли разница между этими двумя подходами?
  • Q.2 Рекомендуется ли использовать один из них в определенных условиях? или я могу использовать любой из них в любое время.
  • Q.3 Для второго вызова я использую асинхронное ожидание в двух местах (клиент-сервер), есть ли в этом какое-то преимущество?

Пожалуйста, направляйте.


person Learner    schedule 28.09.2012    source источник


Ответы (1)


Я не знаю, как выглядит сгенерированный код для WCF, но я ожидаю, что вторая форма будет лучше. (EDIT: прочитайте сообщение в блоге Стивена, чтобы узнать, почему это так. .)

Первый подход создает новую задачу, которая вызывает метод синхронно, блокируя поток на время, необходимое для возврата метода. Поэтому, если у вас есть много этих вызовов одновременно, вы в конечном итоге будете использовать много потоков и, следовательно, памяти.

Я ожидаю, что второй подход будет более "естественно" асинхронным - в основном отправка запроса и последующая обработка ответа в потенциально другом потоке, когда он возвращается.

На ваш последний вопрос:

Для второго вызова я использую асинхронное ожидание в двух местах (клиент-сервер), есть ли в этом преимущество?

Вы используете await в двух местах в оба фрагментах кода. Но да, использование асинхронного кода в обоих случаях определенно дает преимущество. В клиенте вы сохраняете клиентские потоки. На сервере вы сохраняете серверные потоки.

Используя чисто асинхронную версию, вы могли бы иметь сотни вызовов от клиента к серверу, не используя более одного или двух потоков в каждом из этих процессов. В клиенте у вас нет ничего заблокированного, ожидающего ответа — у вас есть только продолжения, готовые к вызову, когда придет ответ. На сервере у вас ничего не блокируется при вызове Thread.Sleep (логический синхронный эквивалент Task.Delay) — у вас просто есть множество продолжений, готовых к запуску, когда истечет задержка.

Так что да, это хорошо с каждой стороны. По сути, вы получаете выгоду везде, где вы его используете.

person Jon Skeet    schedule 28.09.2012
comment
Большое спасибо, Джон. Я знаю о преимуществе отзывчивости при использовании async-await. Ваш ответ ясно объясняет преимущество масштабируемости. Минимальные ресурсы будут использоваться при использовании asycn как на стороне клиента, так и на стороне сервера. Еще раз спасибо за ваш ответ. - person Learner; 28.09.2012
comment
Новые методы *Async на клиентском прокси изначально асинхронны. Я написал сообщение в блоге об async обновлениях WCF< /а>. - person Stephen Cleary; 28.09.2012
comment
@StephenCleary: Спасибо за подтверждение. Это имеет большой смысл. - person Jon Skeet; 28.09.2012