C# 试图并行运行多个HTTP请求,但受到Windows(注册表)的限制

C# 试图并行运行多个HTTP请求,但受到Windows(注册表)的限制,c#,multithreading,dotnet-httpclient,C#,Multithreading,Dotnet Httpclient,我正在开发一个应用程序(winforms C#.NET 4.0),通过一个简单的HTTP请求从第三方访问查找功能。我用一个参数调用一个url,作为回报,我得到一个带有查找结果的小字符串。很简单 然而,挑战是,我必须做很多这样的查找(几千次),我想限制所需的时间。因此,我希望并行运行请求(比如10-20)。我使用线程池来实现这一点,我的代码的简短版本如下所示: public void startAsyncLookup(Action<LookupResult> returnLookupR

我正在开发一个应用程序(winforms C#.NET 4.0),通过一个简单的HTTP请求从第三方访问查找功能。我用一个参数调用一个url,作为回报,我得到一个带有查找结果的小字符串。很简单

然而,挑战是,我必须做很多这样的查找(几千次),我想限制所需的时间。因此,我希望并行运行请求(比如10-20)。我使用线程池来实现这一点,我的代码的简短版本如下所示:

public void startAsyncLookup(Action<LookupResult> returnLookupResult)
{
    this.returnLookupResult = returnLookupResult;

    foreach (string number in numbersToLookup)
    {
        ThreadPool.QueueUserWorkItem(lookupNumber, number);
    }
}

public void lookupNumber(Object threadContext)
{
    string numberToLookup = (string)threadContext;
    string url = @"http://some.url.com/?number=" + numberToLookup;
    WebClient webClient = new WebClient();
    Stream responseData = webClient.OpenRead(url);
    LookupResult lookupResult = parseLookupResult(responseData);

    returnLookupResult(lookupResult);
}
public void startAsyncLookup(操作返回lookupresult)
{
this.returnLookupResult=returnLookupResult;
foreach(numbersToLookup中的字符串编号)
{
QueueUserWorkItem(查找编号,编号);
}
}
public void lookupNumber(对象线程上下文)
{
字符串numberToLookup=(字符串)threadContext;
字符串url=@“http://some.url.com/?number=“+数字查找;
WebClient WebClient=新的WebClient();
Stream responseData=webClient.OpenRead(url);
LookupResult LookupResult=parseLookupResult(responseData);
返回lookupResult(lookupResult);
}
我从另一个地方填写
numbersToLookup
(一个
列表
),调用
startAsyncLookup
,并为其提供回调函数
returnLookupResult
,以返回每个结果。这是可行的,但我发现我没有得到我想要的吞吐量

起初我认为可能是第三方的系统很差,但我排除了这一点,因为我试图同时从两台不同的机器上运行相同的代码。两个人都花了和一个人一样长的时间,所以我可以排除那个人

一位同事告诉我,这可能是Windows的一个限制。我在谷歌上搜索了一下,发现有人说,默认情况下,Windows将对同一web服务器的同时请求数量限制为4(对于HTTP 1.0)和2(对于HTTP 1.1,这实际上符合规范(RFC2068))

上述同一职位也提供了增加这些限制的途径。通过将两个注册表值添加到
[HKEY\U CURRENT\U USER\Software\Microsoft\Windows\CurrentVersion\Internet设置]
(MaxConnectionsPerServer和MaxConnectionsPer1\u 0Server),我可以自己控制这一点

所以,我尝试了这个(从sat到20),重新启动了我的计算机,并尝试再次运行我的程序。不幸的是,这似乎没有任何帮助。在运行批处理查找时,我还关注着资源监视器,我注意到我的应用程序(标题为blackout的应用程序)仍然只使用了两个TCP连接

所以,问题是,为什么这不起作用?我链接到的帖子是否使用了错误的注册表值?这可能不可能在Windows中“黑客”了吗(我在Windows 7上)

如果有人想知道,我也尝试过线程池上MaxThreads的不同设置(从10到100),这似乎根本不会影响我的吞吐量,所以问题也不应该存在。

对于Internet Explorer 8: 运行注册表编辑器并导航到以下项HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE\MAXCONNECTION SPERSERVER

HKEY\U LOCAL\U MACHINE\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE\U MAXCONNECTION SPER1\U 0SERVER

如果缺少功能\u MAXCONNECTIONSPERSERVER和功能\u MAXCONNECTIONSPER1\u 0SERVER,请创建它们。现在为两个子键(上面列出)创建名为iexplore.exe的DWORD值,并将其值设置为10或所需的任何数字。

这是一个问题。它为HTTP连接提供连接管理。 ServicePoint对象允许的默认最大并发连接数为2。
所以,如果你需要增加它,你可以使用属性。只需查看MSDN中的链接,就可以看到一个示例。并设置所需的值。

以便更快地为某人提供参考。要增加每台主机的连接限制,可以在Main()中或在开始发出HTTP请求之前的任何时间执行此操作

   System.Net.ServicePointManager.DefaultConnectionLimit = 1000; //or some other number > 4

在你的主要方法中,开火并忘记这个方法。Icognito用户是正确的,只允许同时播放2个线程

private static void openServicePoint()
{
    ServicePointManager.UseNagleAlgorithm = true;
    ServicePointManager.Expect100Continue = true;
    ServicePointManager.CheckCertificateRevocationList = true;
    ServicePointManager.DefaultConnectionLimit = 10000;
    Uri MS = new Uri("http://My awesome web site");
    ServicePoint servicePoint = ServicePointManager.FindServicePoint(MS);
}

我不明白为什么这会起作用,因为这只会限制IE的限制,而不是一般的限制。。。总之,Incognito的回答解决了我的问题。它不应该是iexplore.exe,但进程可执行文件的名称和限制仅适用于脱离WebBrowser控制的连接。欢迎;)。很高兴它能帮上忙。感谢你们两位提出的好问题和回答。如果我们在servicepointmanager上设置defaultconnectionlimit属性,这就足够了,还是我们还需要更新上述注册表设置?@Rajesh无需更新注册表,只需设置属性值就足够了。需要注意的一点是,默认限制如此低是有原因的。基本上是一个好的互联网公民。如果这影响到您自己的服务,那么增加数量显然不是问题,因为您可以控制负载。对于不属于您的url,您应该事先与所有者联系,或者与您正在呼叫的端点保持联系。不幸的是,这是一种在小型和/或写得不好的站点上进行简单DOS攻击的方法,即使这不是您的意图。屏幕截图链接给出http 404错误:(我们知道为什么有两个键FEATURE_MAXCONNECTIONSPERSERVER和FEATURE_MAXCONNECTIONSPER1_0SERVER吗?这两个独立键的意义是什么?从逻辑上讲,应该只有一个键。Linked post(pctools.com)不再存在。