tug*_*erk 7 .net c# system.net http httplistener
我创建了以下简单的HttpListener同时提供多个请求(在.NET 4.5上):
class Program {
static void Main(string[] args) {
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://+:8088/");
listener.Start();
ProcessAsync(listener).ContinueWith(task => { });
Console.ReadLine();
}
static async Task ProcessAsync(HttpListener listener) {
HttpListenerContext ctx = await listener.GetContextAsync();
// spin up another listener
Task.Factory.StartNew(() => ProcessAsync(listener));
// Simulate long running operation
Thread.Sleep(1000);
// Perform
Perform(ctx);
await ProcessAsync(listener);
}
static void Perform(HttpListenerContext ctx) {
HttpListenerResponse response = ctx.Response;
string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// You must close the output stream.
output.Close();
}
}
Run Code Online (Sandbox Code Playgroud)
我使用Apache Benchmark Tool来加载测试.当我发出1请求时,我将请求的最长等待时间设置为1秒.例如,如果我发出10个请求,响应的最长等待时间将达到2秒.
您如何更改我的上述代码以使其尽可能高效?
编辑
在@ JonSkeet的回答之后,我更改了以下代码.最初,我尝试模拟阻塞调用,但我想这是核心问题.所以,我把@ JonSkeet的建议改为Task.Delay(1000).现在,下面的代码给出了最大值.等待时间约.10个并发请求1秒:
class Program {
static bool KeepGoing = true;
static List<Task> OngoingTasks = new List<Task>();
static void Main(string[] args) {
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://+:8088/");
listener.Start();
ProcessAsync(listener).ContinueWith(async task => {
await Task.WhenAll(OngoingTasks.ToArray());
});
var cmd = Console.ReadLine();
if (cmd.Equals("q", StringComparison.OrdinalIgnoreCase)) {
KeepGoing = false;
}
Console.ReadLine();
}
static async Task ProcessAsync(HttpListener listener) {
while (KeepGoing) {
HttpListenerContext context = await listener.GetContextAsync();
HandleRequestAsync(context);
// TODO: figure out the best way add ongoing tasks to OngoingTasks.
}
}
static async Task HandleRequestAsync(HttpListenerContext context) {
// Do processing here, possibly affecting KeepGoing to make the
// server shut down.
await Task.Delay(1000);
Perform(context);
}
static void Perform(HttpListenerContext ctx) {
HttpListenerResponse response = ctx.Response;
string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// You must close the output stream.
output.Close();
}
}
Run Code Online (Sandbox Code Playgroud)
在我看来,你最终会听到听众的分歧.在内部ProcessAsync,您启动一个新任务来侦听(通过Task.Factory.StartNew),然后在方法结束时ProcessAsync 再次调用.怎么能完成?目前尚不清楚这是否是导致性能问题的原因,但它看起来一般都是一个问题.
我建议将代码更改为一个简单的循环:
static async Task ProcessAsync(HttpListener listener) {
while (KeepGoing) {
var context = await listener.GetContextAsync();
HandleRequestAsync(context);
}
}
static async Task HandleRequestAsync(HttpListenerContext context) {
// Do processing here, possibly affecting KeepGoing to make the
// server shut down.
}
Run Code Online (Sandbox Code Playgroud)
现在上面的代码忽略了返回值HandleRequestAsync.您可能希望保留"当前正在运行"任务的列表,并且当您被要求关闭时,请使用await Task.WhenAll(inFlightTasks)以避免过快地关闭服务器.
另请注意,这Thread.Sleep是阻塞延迟.异步延迟将是await Task.Delay(1000).