使用并行性来加速代码

时间:2018-02-09 23:56:57

标签: c# .net console-application

我已经创建了一个发送HTTP请求(GET)的工具(读取从.txt发送的内容的信息),捕获json并解析它+将其写入.txt。该工具是一个针对.NET Framework 4.5的控制台应用程序。

我可以在“多线程”的帮助下加快速度吗?

        System.IO.StreamReader file =
            new System.IO.StreamReader(@"file.txt");
        while ((line = file.ReadLine()) != null)
        {
            using (var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }))
            {
                client.BaseAddress = new Uri("https://www.website.com/");
                HttpResponseMessage response = client.GetAsync("index?userGetLevel=" + line).Result;
                response.EnsureSuccessStatusCode();
                string result = response.Content.ReadAsStringAsync().Result;
                dynamic json = JObject.Parse(result);
                string level = json.data.level;

                if (level == "null")
                {
                    Console.WriteLine("{0}: User does not exist.", line);
                }
                else
                {
                    Console.WriteLine("{0}: User level is {1}.", line, level);

                    using (StreamWriter sw = File.AppendText(levels.txt))
                    {
                        sw.WriteLine("{0} : {1}", line, level);
                    }
                }

            }
        }

        file.Close();

问题解答:

“加速什么?”:我想加快整个过程(每次发送的请求数量,而不是它发送的速度。

“有多少请求?”:该工具从文本文件中读取字符串并将该信息放入URL的一部分,然后捕获响应,然后将其放入结果中。文本。我想一次增加它的速度/它做多少。

“请求可以同时发生还是依赖于先前的请求响应?”:是,不,它们不依赖。

“您的网络服务器是否对并发请求数量施加限制?”:否。

“典型请求需要多长时间?”:请求+每个请求在控制台上显示响应的时间略多于1/3秒。

1 个答案:

答案 0 :(得分:1)

有几种不对称编程的方法,其中一种可能是这样的:

var messages = new ConcurrentQueue<string>();
//or
//var lockObj = new object();

public int main()
{
    var fileText = File.ReadAllLines(@"file.txt");

    var taskList = new List<Task>();
    foreach (var line in fileText)
    {
        taskList.Add(Task.Factory.StartNew(HandlerMethod, line));
        //you can control the amount of produced task if you want:
        //if(taskList.Count > 20)
        //{
        //    Task.WaitAll(taskList.ToArray());
        //    taskList.Clear();
        //}
    }
    Task.WaitAll(taskList.ToArray()); //this line may not work as I expected.

    //for the first way
    var results = new StringBuilder();
    foreach (var msg in messages)
    {
        results.AppendLine("{0} : {1}", line, level);
    }
    File.WriteAllText("path", results.ToString());
}

要编写结果,您可以使用公共并发集合或使用lock pattern

public void HandlerMethod(object obj)
{
    var line = (string)obj;
    var result = string.Empty;
    using (var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }))
    {
        client.BaseAddress = new Uri("https://www.website.com/");
        HttpResponseMessage response = client.GetAsync("index?userGetLevel=" + line).Result;
        response.EnsureSuccessStatusCode();
        string result = response.Content.ReadAsStringAsync().Result;
        dynamic json = JObject.Parse(result);
        result = json.data.level;
    }

    //for the first way
    if (string.IsNullOrWhiteSpace(result))
    {
        messages.Enqueue("{0}: User does not exist.", line);
    }
    else
    {
        messages.Enqueue("{0}: User level is {1}.", line, result);
    }

    //for the second way
    //lock(lockObj)
    //{
    //    using (StreamWriter sw = File.AppendText(levels.txt))
    //    {
    //        sw.WriteLine("{0} : {1}", line, level);
    //    }
    //}
}