Действительно асинхронный сервис WCF - PullRequest
8 голосов
/ 09 ноября 2011

Я внедряю асинхронный сервис.После оценки примера Microsoft мне интересно, действительно ли их подход является асинхронным.Я почти уверен, что это так, но некоторые примеры, которые я видел в Интернете и параметр AsyncCallback, вызывают у меня удивление.

В соответствии с примером нам нужно реализовать Begin и Конец пара методов, подобная этой:

public IAsyncResult BeginGetAcmeAnvil(AsyncCallback callback, object state)
{
  // Starts synchronous task
  var acmeAsyncResult = new AcmeAsyncResult<Anvil>
  {
     Data = new Anvil()
  };      
  return acmeAsyncResult;
}

public Anvil EndGetAcmeAnvil(IAsyncResult result)
{
  var acmeAsyncResult = result as AcmeAsyncResult<Anvil>;

  return acmeAsyncResult != null
    ? acmeAsyncResult.Data
    : new Anvil();
}

Довольно просто, но почему у нас есть параметр AsyncCallback?Разве мы не должны вызывать callback, который, в свою очередь, вызовет метод End ?

Это то, что я имею в виду:

public delegate void AsyncMethodCaller(AcmeAsyncResult<Anvil> acmeAsyncResult, 
                                       AsyncCallback callback);

public IAsyncResult BeginGetAcmeAnvil(AsyncCallback callback, object state)
{
  var acmeAsyncResult = new AcmeAsyncResult<Anvil>();
  var asyncMethodCaller = new AsyncMethodCaller(GetAnvilAsync);

  // Starts asynchronous task
  asyncMethodCaller.BeginInvoke(acmeAsyncResult, callback, null, null);

  return acmeAsyncResult;
}

private void GetAcmeAnvilAsync(AcmeAsyncResult<Anvil> acmeAsyncResult,
                               AsyncCallback callback)
{
  acmeAsyncResult.Data = new Anvil();
  callback(acmeAsyncResult);  // Triggers EndGetAcmeAnvil
}

public Anvil EndGetAcmeAnvil(IAsyncResult result)
{
  var acmeAsyncResult = result as AcmeAsyncResult<Anvil>;

  return acmeAsyncResult != null
    ? acmeAsyncResult.Data
    : new Anvil();
}

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

Ответы [ 2 ]

5 голосов
/ 30 ноября 2011

Я нашел хорошую статью , объясняющую, как получить максимальную производительность от вашей службы Async WCF.

Суть:

  1. не выполняйте тяжелую работу в методе Begin и
  2. сделать обратный вызов для запуска метода End .

Вот выдержка из текста:

Для лучшей производительности, вот два принципа, когда вы вызываете / внедряете вышеуказанный асинхронный шаблон:

  • Принцип 1: Не выполняйте тяжелую работу внутри метода Begin ...

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

  • Принцип 2: Избегайте вызова метода End в той же нити, что и у метода Begin .

    Метод End обычно блокируется. Он ожидает завершения операции. Если вы реализуете метод End , вы увидите, что он на самом деле вызывает IAsyncResult.WaitHandle.WaitOne () . С другой стороны, как обычная реализация, это WaitHandle является выделенной задержкой ManualResetEvent . Пока вы не позвоните, он не будет выделен вообще. Для быстрых операций это довольно дешево. Однако, как только End вызван, вы должны будете выделить его. Правильное место для вызова End - от callback операции. Когда вызывается callback , это означает, что работа по блокировке действительно завершена. На этом этапе вы можете позвонить End , чтобы получить данные, извлеченные без ущерба для производительности.

2 голосов
/ 10 ноября 2011

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

Если бы вы вызывали метод end с помощью обратного вызова, вам пришлось бы обрабатывать синхронизацию, что делает шаблон немного более сложным (как вы можете видеть в примерах кодирования).Цель этого шаблона не в том, чтобы вы по-настоящему знали о потоках, вы просто хотите закодировать свою долгосрочную операцию, не думая о деталях реализации потоков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...