Чем отличается асинхронное программирование от потоков?

Я читал некоторыеasync статьи здесь:http://www.asp.net/web-forms/tutorials/aspnet-45/using-asynchronous-methods-in-aspnet-45 и автор говорит:

When you’re doing asynchronous work, you’re not always using a thread. For example, when you make an asynchronous web service request, ASP.NET will not be using any threads between the async method call and the await.

Так что я пытаюсь понять, как это становитсяasync если мы не будем использовать какие-либо потоки для одновременного выполнения? Что значит "вы" не всегда используете тему. "

Позвольте мне сначала объяснить, что я знаю о работе с потоками (быстрый пример, конечно, потоки могут использоваться в других ситуациях, отличных от методологии пользовательского интерфейса и рабочего здесь)

You have UI Thread to take input, give output. You can handle things in UI Thread but it makes the UI unresponsive. So lets say we have a stream-related operation and we need to download some sort of data. And we also allow users to do other things while it is being downloaded. We create a new worker thread which downloads the file and changes the progress bar. Once it is done, there is nothing to do so thread is killed. We continue from UI thread.

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

Разве это не то же самое дляasync программирование? Если нет, то в чем разница? Я прочитал этоasync программирование используетThreadPool чтобы вытащить темы, хотя.

Ответы на вопрос(3)

Давайте представим, что вы реализуете веб-приложение и каждый запрос клиента приходит к ваш сервер, вам нужно сделать запрос к базе данных. Когда приходит запрос клиента, пул потоков поток позвонит в ваш код. Если вы теперь выполните запрос к базе данных синхронно, поток заблокирует в течение неопределенного времени ожидания, пока база данных ответит результатом. Если за это время приходит другой клиентский запрос, пул потоков должен будет создать другой поток и снова поток заблокирует, когда он сделает другой запрос к базе данных. По мере того, как поступает все больше и больше запросов клиентов, создается все больше и больше потоков, и все эти потоки блокируют ожидание ответа базы данных. В результате ваш веб-сервер выделяет много системных ресурсов (потоков и их памяти), которые едва даже используются! И что еще хуже, когда база данных отвечает с различными результатами, потоки становятся разблокирован, и все они начинают выполняться. Но так как у вас может быть много запущенных потоков и относительно В некоторых ядрах процессора Windows вынуждена часто переключать контексты, что снижает производительность даже Больше. Это не способ реализовать масштабируемое приложение.

Чтобы прочитать данные из файла, я теперь вызываю ReadAsync вместо Read. ReadAsync внутренне выделяет Объект задачи для представления ожидающего завершения операции чтения. Затем ReadAsync вызывает функцию ReadFile для Win32 (# 1). ReadFile выделяет свой IRP, инициализирует его так же, как это было в синхронный сценарий (# 2), а затем передает его ядру Windows (# 3). Windows добавляет IRP в очередь IRP драйвера жесткого диска (# 4), но теперь, вместо того, чтобы блокировать ваш поток, ваш поток разрешено вернуться к вашему коду; Ваш поток немедленно возвращается из своего вызова в ReadAsync (# 5, # 6, и № 7). Теперь, конечно, IRP еще не обязательно обработан, поэтому вы не можете иметь код после ReadAsync, который пытается получить доступ к байтам в переданном байте [].

Первый раз, когда я увиделasync а такжеawaitЯ думаю, они были синтаксическим C # сахаром для модели асинхронного программирования. Я был неправ,async а такжеawait больше, чем это. Это совершенно новый асинхронный шаблон Асинхронный шаблон на основе задач,http://www.microsoft.com/en-us/download/details.aspx?id=19957 хорошая статья для начала. Большинство классов FCL, которые дополняют TAP, являются методами вызова APM (BegingXXX () и EndXXX ()). Вот две привязки кода для TAP и AMP:

Образец TAP:

    static void Main(string[] args)
    {
        GetResponse();
        Console.ReadLine();
    }

    private static async Task<WebResponse> GetResponse()
    {
        var webRequest = WebRequest.Create("http://www.google.com");
        Task<WebResponse> response = webRequest.GetResponseAsync();
        Console.WriteLine(new StreamReader(response.Result.GetResponseStream()).ReadToEnd());
        return response.Result;
    }

Образец APM:

    static void Main(string[] args)
    {
        var webRequest = WebRequest.Create("http://www.google.com");
        webRequest.BeginGetResponse(EndResponse, webRequest);
        Console.ReadLine();
    }

    static void EndResponse(IAsyncResult result)
    {
        var webRequest = (WebRequest) result.AsyncState;
        var response = webRequest.EndGetResponse(result);
        Console.WriteLine(new StreamReader(response.GetResponseStream()).ReadToEnd());
    }

Наконец, эти два будут одинаковыми, потому что GetResponseAsync () вызывает BeginGetResponse () и EndGetResponse () внутри. Когда мы отразим исходный код GetResponseAsync (), мы получим такой код:

task = Task<WebResponse>.Factory.FromAsync(
       new Func<AsyncCallback, object, IAsyncResult>(this.BeginGetResponse), 
       new Func<IAsyncResult, WebResponse>(this.EndGetResponse), null);

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

  1. like in your mentioned article, there are memory cost and CLR are
    limitation on thread pool.
  2. Context switch will happen. On the other hander, asynchronous will not create any thread manually and it will not have context switch when the the IO-bound operations return.

Вот картина, которая может помочь понять различия:

enter image description here

Эта диаграмма взята из статьи MSDN & quot;Асинхронные страницы в ASP.NET 2.0& quot ;, в котором очень подробно объясняется, как работает старая асинхронная работа в ASP.NET 2.0.

Об Асинхронной Модели Программирования, пожалуйста, узнайте больше из статьи Джеффри Рихтера & quot;Реализация модели асинхронного программирования CLR& quot ;, также есть более подробная информация о его книге 'CLR via Csharp 3rd Edition' & quot; в главе 27.

Решение Вопроса

Потоки не нужны для асинхронного программирования.

& Quot; Асинхронный & Quot; означает, что API не блокируетcalling нить. Оно делаетnot означает, что есть еще одна тема, котораяis блокировка.

Сначала рассмотрим пример пользовательского интерфейса, на этот раз с использованием реальных асинхронных API:

  1. You have UI Thread to take input, give output.
  2. You can handle things in UI Thread but it makes the UI unresponsive.
  3. So lets say we have a stream-related operation and we need to download some sort of data.
  4. And we also allow users to do other things while it is being downloaded.
  5. We use asynchronous APIs to download the file. No worker thread is necessary.
  6. The asynchronous operation reports its progress back to the UI thread (which updates the progress bar), and it also reports its completion to the UI thread (which can respond to it like any other event).

Это показывает, как может быть задействован только один поток (поток пользовательского интерфейса), но также могут выполняться асинхронные операции. Вы можете запустить несколько асинхронных операций, но при этом задействовать только один поток - никакие потоки на них не заблокированы.

async/await обеспечивает очень хороший синтаксис для запуска асинхронной операции, а затем ее возврата и продолжения работы остальной части метода после завершения этой операции.

ASP.NET аналогичен, за исключением того, что он не имеет основного потока / пользовательского интерфейса. Вместо этого он имеет «контекст запроса»; за каждый неполный запрос. Потоки ASP.NET происходят из пула потоков и входят в «контекст запроса». когда они работают по запросу; когда они "закончили", они выходят из своего "контекста запроса" и вернитесь в пул потоков.

ASP.NET отслеживает незавершенные асинхронные операции для каждого запроса, поэтому, когда поток возвращается в пул потоков, он проверяет, выполняются ли какие-либо асинхронные операции для этого запроса; если их нет, то запрос завершен.

Итак, когда выawait Неполная асинхронная операция в ASP.NET, поток будет увеличивать этот счетчик и возвращать. ASP.NET знает, что запрос не завершен, поскольку счетчик не равен нулю, поэтому он не завершает ответ. Поток возвращается в пул потоков, и в этот момент: естьno темы, работающие над этим запросом.

Когда асинхронная операция завершается, она планирует остаток отasync метод к контексту запроса. ASP.NET захватывает один из своих потоков обработчика (который может быть или не быть тем же потоком, который выполнил более раннюю частьasync метод), счетчик уменьшается, и поток выполняетasync метод.

ASP.NET vNext немного отличается; больше поддержки асинхронных обработчиков во всей структуре. Но общая концепция та же самая.

Для дополнительной информации:

Ваш ответ на вопрос