我使用 System.Net 命名空间中的标准 HttpListener 。当我使用 Task.Delay 来模拟服务器端的一些工作(没有等待)和使用Apache基准测试服务器时,它会提供良好的结果(2000 rps)。但是当我等待"等待"带宽约为9 rps(根据Apache Benchmark)。为什么它会像这样?欣赏答案。
private async Task Listen()
{
while (listener.IsListening)
{
try
{
var context = await listener.GetContextAsync().ConfigureAwait(false);
context.Response.StatusCode = (int)HttpStatusCode.OK;
// good without await
await Task.Delay(100).ConfigureAwait(false);
using (var sw = new StreamWriter(context.Response.OutputStream))
{
await sw.WriteAsync("<html><body>Hello</body></html>");
await sw.FlushAsync();
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
public async Task Run()
{
listener.Start();
Task.Run(() => Listen());
}
答案 0 :(得分:4)
这是因为您插入的暂停会延迟循环。
您只接受该行的请求:
await listener.GetContextAsync()
在同一个循环中。
这意味着您必须等待上一个请求完成才能接受新的上下文。
最有可能的是,您希望同时处理接受的上下文。为了达到这个目的,你应该在一个紧密的循环中接受上下文,然后将请求的处理分离到另一个没有“挂起”的地方。接受循环。
在最简单的情况下,你可以发现并忘记&#34; ......
while (listener.IsListening)
{
var context = await listener.GetContextAsync().ConfigureAwait(false);
HandleContextAsync(context); //note: not awaited
}
...实际上,您需要更加思考如何跟踪HandleContextAsync
方法中的异常。
答案 1 :(得分:1)
创建Delay()
任务并允许其在自己的时间运行,而不会进一步影响创建方法。如果您在该任务上既没有await
(异步)或Wait()
(同步),那么创建方法会立即继续,使其显示为“快速”。 await
实际上等待延迟任务完成,但是这样做意味着线程不会阻塞并且可以同时执行其他工作。您的其他版本并非等待,,同步或其他方式。延迟任务被创建并运行,但由于没有其他任何事情在它完成时关心,它只是被执行并且垃圾收集在该方法中不再发挥作用。
答案 2 :(得分:0)
这是因为您在处理下一个请求之前等待了100毫秒,因此您每秒最多可处理10个请求。没有等待的Task.Delay根本不会影响你的应用程序,你可以删除这一行,结果仍然是每秒处理2000个请求。