是否可以超时调用HttpListener.GetContext?

问题描述 投票:0回答:2

根据 HttpListener 参考,对 HttpListener.GetContext 的调用将被阻塞,直到它从客户端获取 HTTP 请求。

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

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

因此,总会有一个线程(如果您使用多线程)无法返回,因为它在等待请求时被阻塞。

我错过了什么吗?

更新:

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

c# httplistener
2个回答
9
投票

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

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

上面会阻塞线程,直到侦听器收到分配给侦听器的 heder 定义的有效内容,或者由于某些异常而终止侦听器线程并将结果返回给 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 没有指示超时或错误,则仅调用listener.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再次监听


2
投票

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

BeginGetContext 和 EndGetContext——即异步操作——就是你想要的。

Begin 和 End 方法的工作原理是,Begin 说“当 X 准备好时向我发出信号”,End 说“将您刚刚向我发出信号的 X 给我”。当然,后者理论上会阻塞,但会瞬间返回。

© www.soinside.com 2019 - 2024. All rights reserved.