【问题标题】:Why won't my .net app make more than 10 concurrent WebClient requests?为什么我的 .net 应用程序不会发出超过 10 个并发 WebClient 请求?
【发布时间】:2012-10-27 19:48:42
【问题描述】:

我试图了解 C# 中的异步/等待和 Windows 中的 I/O 完成端口的复杂性,并在此过程中编写代码来验证我的假设。

据我了解,调用WebClient.DownloadStringTaskAsync(...)会使当前线程注册一个带有I/O完成端口的I/O操作(这可能有点模糊,我还不了解细节),它会创建一个Task<string>,它将继续执行代码。在某些时候,它会遇到给定任务的await。那时,它将从当前方法返回(嗯,它将退出某个范围,我不确定这个范围是否可能不是方法——我可能应该检查生成的状态机以了解该部分) .一旦 I/O 操作完成,将从线程池中抓取一个线程,将 I/O 操作的结果传递给它,然后执行刚才提到的其余范围。

我已尝试验证此行为,但仅在此 C# 代码出现问题之前得到了验证:

class Program
{
    static void Main(string[] args)
    {
        ThreadPool.SetMaxThreads(30, 30);
        Console.WriteLine("Connection limit is {0}", ServicePointManager.DefaultConnectionLimit);
        for (int i = 0; i < 30; i++)
        {
            FetchAsync(i);
        }

        Console.WriteLine("Done starting requests");
        Console.ReadKey();
    }

    private async static void FetchAsync(int num)
    {
        WebClient wc = new WebClient();
        string result = await wc.DownloadStringTaskAsync("http://localhost/slow/index/15");
        Console.WriteLine("Done #{0}", num);
    }
}

如您所见,我正在使用WebClient 为网页创建 30 个请求(我知道这很慢,需要 15 秒才能响应)。运行此代码,我观察到以下行为: 15 秒后,前 10 个请求完成。再过 15 秒,另外 10 个请求完成,再过 15 秒,其余请求完成。因此,似乎一次只有 10 个未完成的请求(使用 perfmon 我已经验证被调用的 Web 应用程序有 10 个当前请求)。这是为什么?我期待 30 个并发请求,因为我已经按照上面的代码设置了线程池的最大线程数。

This SO question 让我相信ServicePointManager 可能与它有关,但由于DefaultConnectionLimit 只有2 我想没有联系。

我意识到这是对一个相当简单的问题的冗长描述。我希望它能让别人更容易准确地指出我的假设在哪里是错误的。

我在 Windows 7 64 位机器上运行它。

【问题讨论】:

  • 您是在 Windows Server 操作系统还是客户端操作系统(例如 Win 7)上运行它?在客户端 Windows 版本中,网络活动过去存在固有限制。
  • 感谢您的评论。我更新了问题:我在 64 位 Thinkpad 上运行 Windows 7。你知道这些限制是否可以改变(或至少检查)吗?
  • 嗯。你能检查你的 Windows 日志中的事件 ID 4228 吗? community.spiceworks.com/windows_event/show/3080-tcpip-4228
  • 我最初指的是一个限制,以防止人们在文件服务器上使用客户端操作系统。还没有看到这一点得到证实,但我在谷歌上搜索找到了我刚刚发布的链接。所以它可能完全不同。
  • @Rune TPL 还尝试优化您使用的线程数。尝试使用纯Thread 类。

标签: c# asynchronous webclient threadpool async-await


【解决方案1】:

您的客户端可以发送任意多个并发请求。但是,您的服务器是 localhost。客户端 Windows 操作系统对 Web 应用程序中的并发请求数有限制(因此您必须购买服务器许可证)。此限制为 10。您对此无能为力。

顺便说一句,您的应用正在使用异步 IO,因此在 IO 运行时您不需要任何线程(甚至不需要隐式线程池线程)。这不是你的问题。

【讨论】:

  • 我可以有比池中的线程更多的未完成请求,这正是我在遇到上述行为时试图证明的。无论如何,现在一切都说得通了。当我针对 WS2008 运行它时,ServicePoint.ConnectionLimit 就会启动。当我提出它时,我可以得到尽可能多的未完成请求。谢谢,非常感谢。
猜你喜欢
  • 1970-01-01
  • 2018-07-21
  • 2014-10-07
  • 2020-09-30
  • 1970-01-01
  • 2011-02-02
  • 2014-08-26
  • 2019-09-19
  • 1970-01-01
相关资源
最近更新 更多