Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多线程httprequests_C#_Multithreading - Fatal编程技术网

C# 多线程httprequests

C# 多线程httprequests,c#,multithreading,C#,Multithreading,我试图创建一个类,在不同的线程上同时发送多个http请求,以加快通过internet获取多个文档的速度 我实现了这一点,但当我从1个线程增加到2个线程时,执行时间会翻倍,从1个线程增加到4个线程,执行时间会翻倍。我认为它应该比1个线程更快 这是代码,也许我有一些问题 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using

我试图创建一个类,在不同的线程上同时发送多个http请求,以加快通过internet获取多个文档的速度

我实现了这一点,但当我从1个线程增加到2个线程时,执行时间会翻倍,从1个线程增加到4个线程,执行时间会翻倍。我认为它应该比1个线程更快

这是代码,也许我有一些问题

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.ComponentModel;

namespace scomA3proj
{
    public class MultithreadedHttpRequests_James : IMultithreadedHttpRequests_James
    {
        List<string> Urls;
        string[] responses;
        public List<string> getHttpResponses(List<string> urls, int numThreads)
        {
            this.Urls = urls;
            responses = new string[urls.Count];
            List<Thread> threads = new List<Thread>();
            for (int i = 0; i < numThreads; i++)
            {
                Thread bgw = new Thread(new ParameterizedThreadStart(bgw_DoWork));
                bgw.Start();
                threads.Add(bgw);
            }
            for (int i = 0; i < numThreads; i++)
            {
                threads[i].Join();
            }
            return responses.ToList();
        }

        void bgw_DoWork(object sender)
        {
            while (true)
            {
                int index = getNext();
                if (index == -1) break;
                string s = Urls[index];
                responses[index] = HttpRequestWrapper.getResponse(s);
            }
        }
        int counter = 0;
        int getNext()
        {
            int res = 0;
            lock (this)
            {
                res = counter;
                counter++;
            }
            if (res >= Urls.Count) 
                return -1;

            return res;
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;

namespace scomA3proj
{
    public sealed class HttpRequestWrapper
    {
        /// <summary>
        /// Gets the HTTP response from a web page. Headers are used based on the useHeaders flag.
        /// </summary>
        /// <param name="url">URI formatted URL(example:"http://www.yahoo.com").</param>
        /// <returns>Returns Html source of requested page.</returns>
        public static string getResponse(string url)
        {
            string result = "";
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                StreamReader reader = new StreamReader(response.GetResponseStream());
                result = reader.ReadToEnd();
            }
            catch (Exception ex)
            {
                result = "error";
            }
            return result;
        }
    }
}

我想可能我连接到的网络路径(大学)限制为每台电脑一个出站连接或其他什么,并惩罚我请求多个…idk…

这里可能会发生一些事情,首先是你达到了web请求允许的连接数限制。默认情况下,该值设置为2,因此要更改该值,可以在函数开始时将其更新为正在使用的线程数

ServicePointManager.DefaultConnectionLimit = 10; 
// 10 should match the number of threads you're executing

除此之外,这取决于您在哪里监视执行时间。如果您正在监视总体执行时间,则应注意您正在执行的其他工作,例如实现一个不使用的队列。

使用新的System.Net.Http.HttpClient,您可以轻松完成此操作,而无需滚动自己的代码:

public class ThreadedHttpGetter
{
    public IEnumerable<Task<HttpResponseMessage>> GetResponses(IEnumerable<string> uris)
    {
        foreach (string uri in uris)
        {
            using (var httpClient = new HttpClient())
            {
                yield return httpClient.GetAsync(uri);
            }
        }
    }
}
公共类ThreadedHttpGetter
{
公共IEnumerable GetResponses(IEnumerable URI)
{
foreach(uri中的字符串uri)
{
使用(var httpClient=new httpClient())
{
返回httpClient.GetAsync(uri);
}
}
}
}
使用以下代码对cnn.com运行10次迭代(如上所述):

    [Test]
    public void YieldResponse()
    {
        IEnumerable<Task<HttpResponseMessage>> responses = new ThreadedHttpGetter().GetResponses(Enumerable.Repeat(uri, iterations));
        Console.WriteLine(responses.Count());
    }
[测试]
公众回应(
{
IEnumerable responses=new ThreadedHttpGetter().GetResponses(Enumerable.Repeat(uri,迭代));
Console.WriteLine(responses.Count());
}
导致控制台输出为:

十, 测试时间为280毫秒

显然,这将取决于网络连接的容量和提供响应的站点

更新:

我刚刚偶然发现了Stephen Toub的这篇博文。这真的是你想要的,他甚至在评论中给出了一个具体的例子,特别详细说明了你想要什么


是的……不要问……我尝试了一些东西,但忘记了删除它。我不知道这是否相关,但我尝试使用PowerShell作业执行类似的操作,而不是直接在.NET中创建线程。我遇到了与您类似的性能问题。我很想看看这个问题还带来了什么其他的想法。您在哪里捕获请求时间的开始和结束?或者,您只是捕获了总体执行时间吗?我找不到其他任何东西。是时候进行printf调试了:在代码中调用Debug.WriteLine和print操作和时间。我按原样运行了您的代码,它的伸缩性非常好。1个线程在58秒内执行227个请求,15个线程在10秒内执行。你想找哪一页?可能是你的本地网站减慢了速度?在www.cnn.com上试一试——它很重——我在单元测试中确实试过了。这毫无帮助。我正在40个文档上尝试这个。我不认为队列会影响执行时间,因为使用1个线程需要7秒来完成=p…我从那时起就删除了它。当你说执行时间加倍时,我们谈论的是什么程度的时间?如果您只做了一个请求,那么请求是否相当快?这是毫秒还是秒的问题?单线程…~7秒处理40个请求…2线程~14秒处理40个请求..4线程~28秒处理40个请求等等…James,你应该在自己的服务器实例上尝试你的应用程序;根据之前的一些聊天,您似乎正在其他网站上使用它,这些网站可能会对您的请求使用任何形式的速率限制。
    [Test]
    public void YieldResponse()
    {
        IEnumerable<Task<HttpResponseMessage>> responses = new ThreadedHttpGetter().GetResponses(Enumerable.Repeat(uri, iterations));
        Console.WriteLine(responses.Count());
    }