c# - 异步等待 Task.Delay 显着降低了基于 HttpListener 的服务器的带宽

标签 c# .net multithreading asynchronous

我使用来自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());
}

最佳答案

这是因为您插入的暂停延迟了循环。

你只接受线上的请求:

await listener.GetContextAsync()

在同一个循环中。

这意味着您必须等待之前的请求完成,然后才能接受新的上下文。

您很可能希望同时处理接受的上下文。为实现这一点,您应该在紧密循环中接受上下文,然后将请求的处理分拆到不会“挂起”接受循环的不同位置。

在最简单的情况下,您可以“即发即弃”...

while (listener.IsListening)
{
    var context = await listener.GetContextAsync().ConfigureAwait(false);
    HandleContextAsync(context); //note: not awaited
}

...实际上,您需要更深入地思考如何在 HandleContextAsync 方法中跟踪异常。

关于c# - 异步等待 Task.Delay 显着降低了基于 HttpListener 的服务器的带宽,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48709023/

相关文章:

c# - 尝试从 linq 正在创建的(匿名类)对象获取属性/字段

c - 多线程数据处理,如果多两个 argvs 总是会出现错误

c# - 从 C++、反向 P/Invoke、混合模式 DLL 和 C++/CLI 调用 C#

c# - 如何打印表格的特定区域?

c# - Sitecore - 以编程方式修改模板的源字段

java - 如何使用 JavaFX 使 Label 的内容在一秒后发生变化?

.net - 使用线程时的socket问题

c# - Ninject with MVC4 - 绑定(bind)bin文件夹中的所有程序集

c# - 测试发出返回非常动态 JSON 的请求的 API 的常用方法是什么

c# - MongoDB如何检查是否存在