Написание службы, работающей на IIS.
В основном выглядит так:
void ProcessRequest(HttpContext context)
{
<Init Stuff>
<Access DB> // This may potentially stall for DB access
<Write Output to conext stream>
}
Задерживая поток в разделе , мы в основном блокируем один из потоков службы IIS. Итак, поиск способа обойти это:
IAsyncResult BeginProcessRequest(HttpContext context,AsyncCallback cb,Object extraData)
{
this.del = new AsyncTaskDelegate(ProcessRequest);
this.del.BeginInvoke(context, cb, extraData);
}
void EndProcessRequest(IAsyncResult result)
{
this.del.EndInvoke(ar);
}
Похоже, он создает другой поток для вызова ProcessRequest (). Таким образом, мы все еще останавливаемся на , но на этот раз мы останавливаемся, используя поток, который не принадлежит IIS. Для меня это красиво и симметрично, и код остается чистым и легко читаемым.
Разговаривая с коллегой, он говорит, что это ничего не купит, так как нить все еще застопорилась. Я согласен, но возражаю, что это не нить IIS, поэтому она что-то мне покупает. НО он утверждает, что если мы используем BeginProcessRequest (), чтобы убедиться, что только выполняется асинхронно, то мы можем купить намного больше, так как никакие потоки не будут остановлены.
Это псевдокод, поскольку я не проработал детали:
void ProcessRequest(HttpContext context)
{ /* Do Nothing */ }
IAsyncResult BeginProcessRequest(HttpContext context,AsyncCallback cb,Object extraData)
{
<Init Stuff>
this.command = <Access DB>.getSQLCommand();
this.command.BeginExecuteNonQuery(cb,extraData); // Assume we want to wait for this to complete.
}
void EndProcessRequest(IAsyncResult result)
{
this.command.EndExecuteNonQuery(result);
<Write Output to conext stream>
}
Я вижу, что преимущество в том, что это не останавливает поток, выполняющий BeginExecuteNonQuery (). Но для этого требуется, чтобы базовая реализация использовала select (), чтобы определить, когда в вызове БД действительно есть данные, ожидающие чтения. В то время как более простой способ реализовать это, было бы просто остановить поток, ожидающий ответа (в этом случае добавление дополнительной гранулярности ничего не покупает).
Так есть ли у кого-нибудь ссылки, указывающие, что на самом деле лучший метод?
Или есть заметки о том, как работает базовая реализация BeginExecuteNonQuery ()?
Или просто любая общая информация, которая может помочь.
Спасибо
Edit:
Класс SqlConnection содержит пул потоков.
Таким образом, когда вы выполняете BeginExecuteNonQuery () для SqlCommand, ему фактически не нужно создавать поток. Запрос отправляется, и основной поток управления запускает поток из пула, когда данные возвращаются с SQL-сервера. Таким образом, описанный выше вариант 3 не приводит к потере потоков и не приводит к зависанию потока при выполнении асинхронной операции с БД.