Асинхронные методы и асинхронные делегаты - PullRequest
10 голосов
/ 13 сентября 2009

C # 3.0 в двух словах говорит асинхронные методы и асинхронные делегаты выглядит аналогично, но поведение очень отличается.

Вот что говорится в книге об обоих.

Асинхронные методы

  1. Редко или никогда не блокирует поток.
  2. Begin метод не может сразу вернуться к вызывающей стороне.
  3. Согласованный протокол без поддержки языка C #.

Асинхронные делегаты

  1. Может блокировать на любой промежуток времени
  2. BeginInvoke немедленно вернуться к вызывающей стороне.
  3. Поддержка встроенного компилятора.

В книге также сказано: Цель асинхронных методов - позволить многим задачам выполняться в нескольких потоках; цель асинхронных делегатов - выполнить задачу параллельно с вызывающей стороной .

Когда я изучал метод BeginRead () в System.IO.Stream классе через рефлектор, он использует делегата и вызывает BeginInvoke для этого , Таким образом, асинхронный метод использует внутренний асинхронный делегат.

  1. В таком случае, как можно сказать, что их поведение отличается? Так как он использует делегатов внутри, как возможно сравнение как выше?
  2. Как вы думаете, работа с методом BeginXXX делегата - это способ выполнения функции параллельно с вызывающей стороной?
  3. Как правильно внедрить асинхронные методы, сохранив все преимущества, такие как эффективное использование процессора?

Есть мысли?

Ответы [ 2 ]

7 голосов
/ 13 сентября 2009

По сути, есть два основных поведения, которые вы можете увидеть, когда вызываете BeginFoo () с обратным вызовом.

  1. Работа начинается в фоновом потоке, и этот поток будет использоваться все время, пока работа не будет завершена и не будет вызван обратный вызов (например, потому что работа является синхронной).
  2. Хотя некоторая работа выполняется в фоновом потоке, поток не должен использоваться все время (например, потому что работа включает в себя системный ввод-вывод, который может планировать обратные вызовы, например, в IOCompletionPort).

Когда вы используете делегата, вышеописанное поведение # 1 происходит.

Некоторые API (которые имеют базовую поддержку неблокирующих вызовов IO) поддерживают поведение # 2.

В конкретном случае 'Stream' я не уверен, но я предполагаю, что это абстрактный базовый класс, и поэтому это просто поведение по умолчанию для подкласса, который реализует только синхронную версию Read. Хороший подкласс переопределяет BeginRead / EndRead, чтобы иметь неблокирующую реализацию.

Преимущество # 2, как вы сказали, в том, что вы можете иметь, например, 100 ожидающих вызовов ввода-вывода без использования 100 потоков (потоки стоят дорого).

5 голосов
/ 13 сентября 2009
  1. Реализация может быть другой; например, асинхронный вызов ввода-вывода может использовать порты завершения, чтобы минимизировать затраты для системы, не делая ничего.
  2. Это, безусловно, способ; вы также можете использовать BackgroundWorker, ThreadPool.QueueUserWorkItem или Parallel.For (и т. д.) в .NET 4.0
  3. Зависит от реализации

Я думаю, что книга пытается подчеркнуть, что делегаты всегда включают эту схему:

  • синхронный вызов (Invoke), который может блокировать
  • асинхронный вызов (BeginInvoke), который на самом деле не должен блокироваться, если только пул потоков не заполнен

но это не единственный шаблон. Также; позднее (например, асинхронные методы ввода-вывода в Silverlight или в WebClient): вместо IAsyncResult событие используется для оповещения о завершении.

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