Vb.net 异步httpListener回调是在UI线程上启动的吗?
我希望将httpListener构建成一个小型服务器应用程序。在阅读时,我遇到了下面的代码片段 这看起来很简单,很像。然而,当在一个虚拟项目中测试它时,我发现了一些让我困惑的事情,例如可以直接从回调子函数访问UI对象,我认为这应该会导致一个跨线程异常 为了澄清,我稍微修改了这段代码,使其在一个简单winforms项目的主窗体中运行 我似乎不完全理解代码,例如AsyncWaitHandle.WaitOne()对我来说是全新的Vb.net 异步httpListener回调是在UI线程上启动的吗?,vb.net,asynchronous,httplistener,Vb.net,Asynchronous,Httplistener,我希望将httpListener构建成一个小型服务器应用程序。在阅读时,我遇到了下面的代码片段 这看起来很简单,很像。然而,当在一个虚拟项目中测试它时,我发现了一些让我困惑的事情,例如可以直接从回调子函数访问UI对象,我认为这应该会导致一个跨线程异常 为了澄清,我稍微修改了这段代码,使其在一个简单winforms项目的主窗体中运行 我似乎不完全理解代码,例如AsyncWaitHandle.WaitOne()对我来说是全新的 有人能简要地告诉我这个片段吗?非常感谢您的帮助。此代码片段如下所示: 它
有人能简要地告诉我这个片段吗?非常感谢您的帮助。此代码片段如下所示:
static void Main(字符串[]args)
{
ServicePointManager.DefaultConnectionLimit=500;
ServicePointManager.Expect100Continue=false;
ServicePointManager.MaxServicePoints=500;
HttpListener=新的HttpListener();
listener.Prefixes.Add(“http://localhost:999/");
listener.Start();
BeginGetContext(ListenerCallBack,listener);
Console.ReadLine();
}
私有静态void ListenerCallBack(IAsyncResult结果)
{
HttpListener HttpListener=(HttpListener)result.AsyncState;
//调用EndGetContext以完成异步操作。
HttpListenerContext=httpListener.EndGetContext(结果);
HttpListenerRequest=context.request;
//获取一个响应对象。
HttpListenerResponse=context.response;
//构建一个响应。
string responseString=“你好,世界!”;
byte[]buffer=System.Text.Encoding.UTF8.GetBytes(responseString);
//获取响应流并将响应写入其中。
response.ContentLength64=buffer.Length;
System.IO.Stream输出=response.OutputStream;
输出.写入(缓冲区,0,缓冲区.长度);
//必须关闭输出流。
output.Close();
//我们调用BeginGetContext()为下一个客户机再次发送异步请求
BeginGetContext(ListenerCallBack,httpListener);
}
在C#5和Net 4.5中,我们有同步方法,这将更容易:
static void Main(string[] args)
{
ServicePointManager.DefaultConnectionLimit = 500;
ServicePointManager.Expect100Continue = false;
ServicePointManager.MaxServicePoints = 500;
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://localhost:999/");
listener.Start();
while (true)
{
var t = listener.GetContextAsync();
HttpListenerContext context = t.Result;
HttpListenerRequest request = context.Request;
// Obtain a response object.
HttpListenerResponse response = context.Response;
// Construct a response.
string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// You must close the output stream.
output.Close();
}
}
static void Main(字符串[]args)
{
ServicePointManager.DefaultConnectionLimit=500;
ServicePointManager.Expect100Continue=false;
ServicePointManager.MaxServicePoints=500;
HttpListener=新的HttpListener();
listener.Prefixes.Add(“http://localhost:999/");
listener.Start();
while(true)
{
var t=listener.GetContextAsync();
HttpListenerContext=t.Result;
HttpListenerRequest=context.request;
//获取一个响应对象。
HttpListenerResponse=context.response;
//构建一个响应。
string responseString=“你好,世界!”;
byte[]buffer=System.Text.Encoding.UTF8.GetBytes(responseString);
//获取响应流并将响应写入其中。
response.ContentLength64=buffer.Length;
System.IO.Stream输出=response.OutputStream;
输出.写入(缓冲区,0,缓冲区.长度);
//必须关闭输出流。
output.Close();
}
}
对于您关于UI的“跨线程异常”的另一个问题,您是对的,创建的新线程将具有SynchronizationContext.Current的空值,因为它是线程池线程,我们需要在窗体的SynchronizationContext中执行post()。以下是更多信息和。简单C#Web服务器,带有HttpListener(名称:服务器)、BackgroundWorker(名称:bw#服务器)、2个按钮(名称:btn#U开始和btn#U停止)和文本框(名称:tb#U日志):
static void Main(string[] args)
{
ServicePointManager.DefaultConnectionLimit = 500;
ServicePointManager.Expect100Continue = false;
ServicePointManager.MaxServicePoints = 500;
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://localhost:999/");
listener.Start();
listener.BeginGetContext(ListenerCallBack, listener);
Console.ReadLine();
}
private static void ListenerCallBack(IAsyncResult result)
{
HttpListener httpListener = (HttpListener) result.AsyncState;
// Call EndGetContext to complete the asynchronous operation.
HttpListenerContext context = httpListener.EndGetContext(result);
HttpListenerRequest request = context.Request;
// Obtain a response object.
HttpListenerResponse response = context.Response;
// Construct a response.
string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer,0,buffer.Length);
// You must close the output stream.
output.Close();
// we call BeginGetContext() to send async request again for next coming client
httpListener.BeginGetContext(ListenerCallBack, httpListener);
}
static void Main(string[] args)
{
ServicePointManager.DefaultConnectionLimit = 500;
ServicePointManager.Expect100Continue = false;
ServicePointManager.MaxServicePoints = 500;
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://localhost:999/");
listener.Start();
while (true)
{
var t = listener.GetContextAsync();
HttpListenerContext context = t.Result;
HttpListenerRequest request = context.Request;
// Obtain a response object.
HttpListenerResponse response = context.Response;
// Construct a response.
string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// You must close the output stream.
output.Close();
}
}
public partial class Form1 : Form
{
HttpListener server;
private void btn_start_Click(object sender, EventArgs e)
{
bw_server.RunWorkerAsync(@"http://+:80/");
}
private void bw_server_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
string prefix = e.Argument.ToString();
bw_server.ReportProgress(0, "Starting server...");
if (!bw_server.CancellationPending)
{
try
{
start_server(prefix);
}
catch (Exception ex)
{
bw_server.ReportProgress(0, ex.Message);
bw_server.CancelAsync();
}
}
else
{
e.Cancel = true;
return;
}
}
private void bw_server_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
log(e.UserState.ToString());
}
private void bw_server_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
log("Server was stopped");
}
else
{
log("Server work was completed");
}
}
private void log(string msg)
{
if (String.IsNullOrEmpty(msg)) return;
tb_log.AppendText((tb_log.Text == String.Empty ? String.Empty : Environment.NewLine) + DateTime.Now.ToLongTimeString() + " " + msg);
}
private void btn_stop_Click(object sender, EventArgs e)
{
WebRequest.Create("http://localhost:" + port + "/?stop=1").GetResponse();
bw_server.CancelAsync();
}
private void start_server(string prefix)
{
server = new HttpListener();
if (!HttpListener.IsSupported) return;
if (String.IsNullOrEmpty(prefix))
{
throw new ArgumentException("prefix");
}
server.Prefixes.Add(prefix);
server.Start();
while (server.IsListening)
{
HttpListenerContext context = server.GetContext();
HttpListenerRequest request = context.Request;
if (request.HttpMethod == "GET")
{
HttpListenerResponse response = context.Response;
response.ContentType = "text/html; charset=UTF-8";
if (request.QueryString["stop"] == "1")
{
write_to_resp(response, "server was stopped");
server.Stop();
}
else
{
write_to_resp(response, "bad params");
}
}
}
}
private static void write_to_resp(HttpListenerResponse response, string str_resp)
{
byte[] buffer = Encoding.UTF8.GetBytes(str_resp);
response.ContentLength64 = buffer.Length;
response.OutputStream.Write(buffer, 0, buffer.Length);
}
}