为什么我的.net应用程序会超过10个并发的WebClient请求?

时间:2012-10-27 19:48:43

标签: c# asynchronous webclient threadpool async-await

我正在尝试理解Windows中C#和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位计算机上运行它。

1 个答案:

答案 0 :(得分:6)

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

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