Подтвердить что ты не робот

Асинхронное программирование APM против EAP

Какая разница между асинхронной моделью программирования и асинхронным шаблоном на основе событий?

Какой подход использовать и когда?

4b9b3361

Ответ 1

Модель асинхронного программирования (APM) - это модель, которую вы видите с парами BeginMethod(...) и EndMethod(...).

Например, здесь Socket используется реализация APM:

 var socket = new Socket(AddressFamily.InterNetwork, 
                        SocketType.Stream, ProtocolType.Tcp);

 // ...

 socket.BeginReceive(recvBuffer, 0, recvBuffer.Length, 
                     SocketFlags.None, ReceiveCallback, null);

 void ReceiveCallback(IAsyncResult result)
 {
   var bytesReceived = socket.EndReceive(result);

   if (bytesReceived > 0) { // Handle received data here. }

   if (socket.Connected)
   {
     // Keep receiving more data...
     socket.BeginReceive(recvBuffer, 0, recvBuffer.Length, 
                         SocketFlags.None, ReceiveCallback, null);
   }
 }

Асинхронный шаблон на основе событий (EAP) - это модель, которую вы видите с парами MethodAsync(...) и CancelAsync(...). Обычно есть событие Completed. BackgroundWorker - хороший пример этого шаблона.

Начиная с С# 4.5, оба были заменены шаблоном async/await, который использует библиотеку Task Parallelism (TPL). Вы увидите их, отмеченные Async после имени метода и обычно возвращающие ожидаемые Task или Task<TResult>. Если вы можете настроить таргетинг на .NET 4.5, вы обязательно должны использовать этот шаблон для проекта APM или EAP.

Например, сжатие (потенциально большого) файла асинхронно:

public static async Task CompressFileAsync(string inputFile, string outputFile)
{
  using (var inputStream = File.Open(inputFile, FileMode.Open, FileAccess.Read))
  using (var outputStream = File.Create(outputFile))
  using (var deflateStream = new DeflateStream(outputStream, CompressionMode.Compress))
  {
    await inputStream.CopyToAsync(deflateStream);

    deflateStream.Close();
    outputStream.Close();
    inputStream.Close();
  }
}

Ответ 2

Из кода клиента POV:

EAP: вы настроили обработчик событий для события, чье имя заканчивается в "Completed", а затем вызовите метод, имя которого заканчивается на "Async". Иногда вы можете вызвать метод с именем "Отмена", который может отменить его.

APM: вы вызываете метод, имя которого начинается с "Begin", затем опробуйте его результат или получите обратный вызов, затем вызовите метод, начинающийся с "End".

Насколько я знаю об этих двух, APM реализуется на большинстве классов ввода-вывода BCL и WCF, в основном, на невыгружаемых операциях нижнего уровня (как и в случае отмены, вы просто игнорируете результат). EAP находится на более высокоуровневых классах, т.е. Для загрузки файла, где есть несколько шагов и какое-то значимое поведение отмены.

Итак, если вам нужно выбрать, что реализовать (и вы намеренно ограничиваете себя этими двумя), я предполагаю, что его до того, что вы делаете, можно отменить или нет.

Из клиентского кода POV вы не всегда получаете выбор. Вероятно, лучше всего использовать С# 4.5 Tasks, если вы можете, они могут работать с любым из более старых асинхронных механизмов через обертки.

Ответ 3

Подробный ответ приведен в статье MSDN "Решение о том, как реализовать асинхронный шаблон на основе событий" .

Основная идея этой статьи (и короткий ответ на ваш вопрос) звучит так: "Построить шаблон на основе событий по умолчанию, с возможностью генерации шаблона IAsyncResult"