是否可以在超时的情况下调用HttpListener.GetContext

本文关键字:情况下 调用 HttpListener GetContext 超时 是否 | 更新日期: 2023-09-27 18:23:56

根据HttpListener引用,对HttpListener.GetContext的调用将被阻止,直到它从客户端获得HTTP请求。

我想知道我是否可以指定一个超时,以便在超时后函数将返回。我认为否则是不合理的,因为你不能保证会有一个请求让这个函数返回,那么怎么能终止这个调用呢?

附言:我知道它有一个异步版本(BeginGetContext),但问题仍然存在,因为相应的EndGetContext将阻塞,直到HTTP请求到达。

因此,总会有一个线程(如果你是多线程的)无法返回,因为它在等待请求时被阻止了。

我遗漏了什么吗?

更新:

我发现这个链接很有用。我还发现调用HttpListener.Close()实际上会终止BeginGetContext()创建的等待线程。不知何故,HttpListener.Close()会触发BeginGetContext()注册的回调。因此,在执行HttpListener.EndGetContext()之前,请检查HttpListener是否已停止。

是否可以在超时的情况下调用HttpListener.GetContext

此外,如果您想在进程中逐行等待有限的时间,BeginGetContext将返回一个System.IAsyncResult,暴露AsyncWaitHandle属性

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

Above阻塞线程,直到侦听器接收到由分配给侦听器的heders定义的有效内容,或者由于终止侦听器线程并将结果返回给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,或者只调用侦听器。如果AsyncWaitHandle 没有指示超时或错误,则行中的EndGetContext

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

调用EndGetContext的回调永远不应该被调用,除非HTTP请求已经到达,或者侦听器失败(在这种情况下,EndGetContext将抛出异常)。因此,如果使用得当,它不会阻塞。

BeginGetContext和EndGetContext——也就是异步操作——就是您想要的。

Begin和End方法的工作原理是,Begin说"X准备好时给我发信号",End说"给我你刚刚给我发过信号的X。"自然,后者在理论上会阻塞,但会立即返回。