我看到了很多关于 GeginGetContext 的例子,但我已经填写了所有这些都是浪费时间。也许我错了。让我们来了解一下。让我们以 .Net HttpListener主题的多线程为例:
public class HttpListenerCallbackState
{
private readonly HttpListener _listener;
private readonly AutoResetEvent _listenForNextRequest;
public HttpListenerCallbackState(HttpListener listener)
{
if (listener == null) throw new ArgumentNullException("listener");
_listener = listener;
_listenForNextRequest = new AutoResetEvent(false);
}
public HttpListener Listener { get { return _listener; } }
public AutoResetEvent ListenForNextRequest { get { return _listenForNextRequest; } }
}
public class HttpRequestHandler
{
private int requestCounter = 0;
private ManualResetEvent stopEvent = new ManualResetEvent(false);
public void ListenAsynchronously(IEnumerable<string> prefixes)
{
HttpListener listener = new HttpListener();
foreach (string s in prefixes)
{
listener.Prefixes.Add(s);
}
listener.Start();
HttpListenerCallbackState state = new HttpListenerCallbackState(listener);
ThreadPool.QueueUserWorkItem(Listen, state);
}
public void StopListening()
{
stopEvent.Set();
}
private void Listen(object state)
{
HttpListenerCallbackState callbackState = (HttpListenerCallbackState)state;
while (callbackState.Listener.IsListening)
{
callbackState.Listener.BeginGetContext(new AsyncCallback(ListenerCallback), callbackState);
int n = WaitHandle.WaitAny(new WaitHandle[] { callbackState.ListenForNextRequest, stopEvent});
if (n == 1)
{
// stopEvent was signalled
callbackState.Listener.Stop();
break;
}
}
}
private void ListenerCallback(IAsyncResult ar)
{
HttpListenerCallbackState callbackState = (HttpListenerCallbackState)ar.AsyncState;
HttpListenerContext context = null;
int requestNumber = Interlocked.Increment(ref requestCounter);
try
{
context = callbackState.Listener.EndGetContext(ar);
}
catch (Exception ex)
{
return;
}
finally
{
callbackState.ListenForNextRequest.Set();
}
if (context == null) return;
HttpListenerRequest request = context.Request;
if (request.HasEntityBody)
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(request.InputStream, request.ContentEncoding))
{
string requestData = sr.ReadToEnd();
//Stuff I do with the request happens here
}
}
try
{
using (HttpListenerResponse response = context.Response)
{
//response stuff happens here
string responseString = "Ok";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.LongLength;
response.OutputStream.Write(buffer, 0, buffer.Length);
response.Close();
}
}
catch (Exception e)
{
}
}
}
在这里我们可以看到这个主题的主要部分:
while (callbackState.Listener.IsListening)
{
callbackState.Listener.BeginGetContext(new AsyncCallback(ListenerCallback), callbackState);
int n = WaitHandle.WaitAny(new WaitHandle[] { callbackState.ListenForNextRequest, stopEvent});
...
}
我可以在 +- 所有示例中看到这种模式。我们开始获取 Contex(获取请求 = 获取请求的网络流)之后我们使用 Wait/WaitAny 方法阻塞当前线程,因此线程女巫正在获取请求什么都不做,直到它获得完整请求之后它将获得新请求. 例如,我们有带有大对象的 WCF 请求(在此请求中反序列化,并在另一端以相同的方式序列化),因此我们将等待并浪费时间,直到我们完成对该请求的全部处理。我看到它确实是同步而不是异步方式。取而代之的是,我们可以在开始获得第一个请求后立即开始获得第二个请求,而不是调用等待,而不是阻塞线程。我认为这样我们会有更好的表现。你怎么看?为什么所有的例子都包含Wait?