C# 如何在并行化异步调用时获得最大的出站请求?

C# 如何在并行化异步调用时获得最大的出站请求?,c#,.net,multithreading,asynchronous,.net-4.0,C#,.net,Multithreading,Asynchronous,.net 4.0,通过Fiddler分析下面的代码,我意识到使用并行扩展最多可以获得2个出站请求: new string[] { "http://stackoverflow.com", "http://superuser.com", "http://serverfault.com", "http://stackexchange.com" } .AsParallel() .Select(a => HttpWebR

通过Fiddler分析下面的代码,我意识到使用并行扩展最多可以获得2个出站请求:

new string[] 
    {
        "http://stackoverflow.com",
        "http://superuser.com",
        "http://serverfault.com",
        "http://stackexchange.com"
    }
    .AsParallel()
    .Select(a => HttpWebRequest.Create(a).GetResponse())
    .ToArray()
    ;

我应该使用什么方法来最大化出站请求的数量?

ServicePointManager.DefaultConnectionLimit


在您的情况下,将其设置为4。

默认情况下,PFX会创建该线程数作为您的CPU核心数。这就是为什么你只有两个请求。使用PFX中的Task类并通过Task.WaitAll运行它们。(我希望我的猜测是正确的。)

编辑:示例

var tasks = servers.Select(Task.Create(() => GetResponseCallHere(...))).ToArray();
Task.WaitAll(tasks);

请注意,在这个问题中,我使用了BeginGetResponse方法的同步版本。到目前为止,我发现最大化出站请求的唯一方法是使用该方法的异步版本。但这种方法产生了新的问题,即:

  • 必须将调用方逻辑分为两种方法
  • 很难跟踪是否所有出站呼叫都已完成
  • 处理异常是很困难的
  • 如果要运行的任务数超过线程池大小,那么天知道会发生什么

    new string[] 
    {
        "http://stackoverflow.com",
        "http://superuser.com",
        "http://serverfault.com",
        "http://stackexchange.com"
    }
    .Select(a => HttpWebRequest.Create(a).BeginGetResponse(callback, null))
    .ToArray();
    

  • 根据Wireshark,此代码在我的机器上并行运行所有6个HTTP请求:

    var urls = new string[] 
    {
        "http://stackoverflow.com", 
        "http://superuser.com", 
        "http://serverfault.com",
        "http://stackexchange.com",
        "http://www.howtogeek.com",
        "http://meta.stackoverflow.com" 
    };
    
    var reqs = urls.Select<string, WebRequest>(HttpWebRequest.Create).ToArray();
    var iars = reqs.Select(req => req.BeginGetResponse(null, null)).ToArray();
    var rsps = reqs.Select((req, i) => req.EndGetResponse(iars[i])).ToArray();
    
    var url=新字符串[]
    {
    "http://stackoverflow.com", 
    "http://superuser.com", 
    "http://serverfault.com",
    "http://stackexchange.com",
    "http://www.howtogeek.com",
    "http://meta.stackoverflow.com" 
    };
    var reqs=url.Select(HttpWebRequest.Create.ToArray();
    var iars=reqs.Select(req=>req.BeginGetResponse(null,null)).ToArray();
    var rsps=reqs.Select((req,i)=>req.EndGetResponse(iars[i])).ToArray();
    
    基本上,它为每个URL创建一个
    WebRequest
    ,对每个URL调用
    BeginGetResponse
    ,然后使用
    IAsyncResult
    为每个URL调用
    EndGetResponse


    文档中指出,
    BeginGetResponse
    用于发出HTTP请求。

    不是每台服务器的持久连接限制吗?我尝试过,但没有成功。需要注意的是,如果我不处理连接,我的应用程序将在达到ServicePointManager.DefaultConnectionLimit上指定的未配置连接数时停止,因为默认限制远远大于4。PFX不是基于
    任务构建的吗?是否有指向文档的链接以确认线程数已设置为PFX中的处理器/内核数?默认TaskManagerPolicy是在并行foreach循环启动时创建的。这里是ParallelExtensions_Jun08CTP_Help的文本:“IdealProcessors-获取用于在此TaskManagerPolicy上执行任务的理想处理器数量。默认值等于系统上的实际处理器数量。”这里是到PFX论坛的证明链接:“2008年6月CTP为每个逻辑处理器创建两个线程”;“这只是CTP版本的临时解决方案”@贾德·迪亚斯:你使用的是2008年6月的CTP吗?我使用的是.NET Framework 4.0 beta 2,其中包括最新发布的并行FX版本。现在我测试了你的代码,我意识到它在我的机器上最多可以同时发出7个请求(对于更大的输入阵列)。你是在没有.aspallel()的情况下尝试的吗?我希望差别不大。