Можно ли вызвать HttpListener.GetContext с таймаутом? - PullRequest
9 голосов
/ 08 февраля 2012

Согласно справке HttpListener , вызов HttpListener.GetContext будет блокироваться до тех пор, пока он не получит HTTP-запрос от клиента.

Интересно, могу ли я указать время ожидания, чтобы послетайм-аут, функция вернется.Я думаю, что в противном случае это неразумно, так как вы не можете гарантировать, что будет запрос на возврат этой функции, тогда как можно завершить этот вызов?

PS Я знаю, что существует асинхронная версия (BeginGetContext), НОпроблема остается, потому что соответствующий EndGetContext будет блокироваться до тех пор, пока не поступит HTTP-запрос .

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

Я что-то пропустил?

ОБНОВЛЕНИЕ:

Я нашел эту ссылку , которая будет полезна.Я также обнаружил, что вызов HttpListener.Close () фактически завершает ожидающие потоки, созданные с помощью BeginGetContext ().Каким-то образом HttpListener.Close () запускает обратные вызовы, зарегистрированные BeginGetContext ().Поэтому перед выполнением HttpListener.EndGetContext () проверьте, не остановился ли HttpListener.

Ответы [ 2 ]

6 голосов
/ 13 ноября 2013

Также, если вы хотите сделать построчную обработку процесса, ожидая ограниченное время, BeginGetContext возвращает System.IAsyncResult, открывающий свойство AsyncWaitHandle

var context = listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener);
context.AsyncWaitHandle.WaitOne();

Выше блокирует поток, пока слушатель не получит что-то действительноекак определено хедерами, назначенными слушателю или завершается из-за некоторого исключения, которое завершает поток слушателя и возвращает результат обратно в ListenerCallback.

Но AsyncWaitHandle.WaitOne () может принимать параметры времени ожидания

// 5 seconds timeout
bool success = context.AsyncWaitHandle.WaitOne(5000, true);

if (success == false)
{
    throw new Exception("Timeout waiting for http request.");
}

ListenerCallback может содержать вызов listener.EndGetContext или просто вызвать listener.EndGetContext в строке, если AsyncWaitHandle не указывает ни таймаут, ни ошибка

public static void ListenerCallback(IAsyncResult result)
{
    HttpListener listener = (HttpListener) result.AsyncState;
    // Use EndGetContext to complete the asynchronous operation.
    HttpListenerContext context = listener.EndGetContext(result);
    HttpListenerRequest request = context.Request;
    // Get response object.
    HttpListenerResponse response = context.Response;
    // Construct a response. 
    string responseString = "<HTML><BODY> It Works!</BODY></HTML>";
    byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
    // Write to response stream.
    response.ContentLength64 = buffer.Length;
    System.IO.Stream output = response.OutputStream;
    output.Write(buffer,0,buffer.Length);
    // Close the output stream.
    output.Close();
}

Не забудьте сказать слушателю прослушать сноваиспользуя listener.BeginGetContext

2 голосов
/ 08 февраля 2012

Обратный вызов, который вызывает EndGetContext, никогда не должен вызываться, если только HTTP-запрос не поступил или прослушиватель не прошел (в этом случае EndGetContext вызовет исключение). Таким образом, он не будет блокироваться при правильном использовании.

BeginGetContext и EndGetContext - то есть асинхронные операции - это то, что вы хотите.

Методы Begin и End работают так, что Begin говорит «сигнализируйте мне, когда X готов», а End говорит «дайте мне тот X, о котором вы только что сигнализировали мне». Естественно, последний теоретически заблокирует, но мгновенно вернется.

...