Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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# c语言中并行任务的性能#_C#_Multithreading_Performance_Task - Fatal编程技术网

C# c语言中并行任务的性能#

C# c语言中并行任务的性能#,c#,multithreading,performance,task,C#,Multithreading,Performance,Task,我需要让任务运行得更快,我尝试使用信号量、并行库和线程(尝试为每项工作打开一个,我知道这是最愚蠢的事情),但它们都没有显示出我需要的性能。我不熟悉线程的工作,我需要一些帮助来找到正确的方法并理解任务和线程是如何工作的 以下是函数: public class Test { public void openThreads() { int maxConcurrency = 500; var someWork =

我需要让任务运行得更快,我尝试使用信号量、并行库和线程(尝试为每项工作打开一个,我知道这是最愚蠢的事情),但它们都没有显示出我需要的性能。我不熟悉线程的工作,我需要一些帮助来找到正确的方法并理解任务和线程是如何工作的

以下是函数:

 public class Test
    {
        public void openThreads()
        {
            int maxConcurrency = 500;
            var someWork = get_data_from_database();
            using (SemaphoreSlim concurrencySemaphore = new SemaphoreSlim(maxConcurrency))
            {
                List<Task> tasks = new List<Task>();
                foreach (var work in someWork)
                {
                    concurrencySemaphore.Wait();

                    var t = Task.Factory.StartNew(() =>
                    {
                        try
                        {
                            ScrapThings(work);
                        }
                        finally
                        {
                            concurrencySemaphore.Release();
                        }
                    });

                    tasks.Add(t);
                }

                Task.WaitAll(tasks.ToArray());
            }
        }

        public async Task ScrapThings(Object work)
        {
            HttpClient client = new HttpClient();
            Encoding utf8 = Encoding.UTF8;
            var response = client.GetAsync(work.url).Result;
            var buffer = response.Content.ReadAsByteArrayAsync().Result;
            string content = utf8.GetString(buffer);
            /*
             Do some parse operations, load html document, get xpath, split things, etc 
             */

            while(true) // this loop runs from 1~15 times
            {
                response = client.GetAsync(work.anotherUrl).Result;
                buffer = response.Content.ReadAsByteArrayAsync().Result;
                content = utf8.GetString(buffer);
                if (content == "OK")
                    break;

                await Task.Delay(10000); //I need some throttle here before it tries again
            }
            /*
                Do some parse operations, load html document, get xpath, split things, etc 
                */
            update_things_in_database();
        }
    }
公共类测试
{
公共void openThreads()
{
int-maxConcurrency=500;
var someWork=get_data_from_database();
使用(SemaphoreSlim concurrency semaphore=new SemaphoreSlim(maxConcurrency))
{
列表任务=新列表();
foreach(某些工作中的var工作)
{
concurrency-ysemaphore.Wait();
var t=Task.Factory.StartNew(()=>
{
尝试
{
垃圾(工作);
}
最后
{
并发Maphore.Release();
}
});
任务。添加(t);
}
Task.WaitAll(tasks.ToArray());
}
}
公共异步任务(对象工作)
{
HttpClient=新的HttpClient();
Encoding utf8=Encoding.utf8;
var response=client.GetAsync(work.url).Result;
var buffer=response.Content.ReadAsByteArrayAsync().Result;
字符串内容=utf8.GetString(缓冲区);
/*
执行一些解析操作、加载html文档、获取xpath、拆分内容等
*/
while(true)//此循环运行1~15次
{
response=client.GetAsync(work.anotherUrl).Result;
buffer=response.Content.ReadAsByteArrayAsync().Result;
content=utf8.GetString(缓冲区);
如果(内容=“确定”)
打破
等待任务。延迟(10000);//在它再次尝试之前,我需要一些油门
}
/*
执行一些解析操作、加载html文档、获取xpath、拆分内容等
*/
更新_数据库()中的_事物_;
}
}

我想让这个任务并行运行500次,所有的操作需要18个小时才能完成,我需要减少这个,我使用的是32核/64线程的xeon。我尝试打开500个线程(与信号量和并行库相比性能更好),但感觉不太对劲

我想说,性能的问题不在于如何运行线程,而在于各个线程的性能。根据您使用的.NET/库的版本,可能存在的问题很少

  • 您应该重用
    HttpClient
    实例,原因如下
  • 如果
    work.url
    work.anotherUrl
    使用相同的域子集,则应查看每个端点的连接限制(以及总数)。取决于版本或和。前者用于.NET内核,后者用于.NET内核
  • 解决第一个问题的推荐方法是使用

    还有一些

    UPD

    您在评论中提到您正在使用.NET 4.7.2,因此我建议您首先在应用程序中添加下一行(在开头的某个地方):


    这听起来像是图书馆的工作。对于I/O绑定操作(web请求、数据库更新)和CPU绑定操作(数据解析),可能需要不同的并发级别。TPL数据流允许构建一个管道,其中每个块负责一个操作,数据从一个块流向下一个块。它甚至允许循环图,例如,您可以将一个失败的数据元素抛出回块中,以便可以再次处理它

    有关使用此库的一些示例,请参见或


    TPL数据流库嵌入在.NET Core中,可作为.NET框架使用。

    您确定性能受CPU而非其他因素的限制吗?使用
    ScrapThings
    你有
    等待任务。延迟(10000)//在它再次尝试之前,我需要一些限制-我假设这是因为你避免了对服务器的垃圾邮件和速率限制,但是如果你有500个任务同时进行,那么延迟将不起作用,并且速率也会受到限制。为什么会有这么多像
    client.GetAsync(work.url)这样的阻塞调用.Result
    async
    方法中?听起来您需要具有设置数量的连续threads@BrunoLeyne但为什么不等待client.GetAsync(work.url)
    ?200比1的几率是你的代码导致了性能问题,你认为任务/线程/[选择你的毒药]原因是您从未分析过应用程序。由于Cookie/sessions管理,我无法重用HttpClient。我有86个ScrapThings函数,它们是不同的,因为我需要废弃不同的东西。我从未使用过IHttpClientFactory,我会阅读文档,看看有什么不同。我将花一些时间阅读。1)查看更新2)如果您使用factory或仅使用
    HttpClient
    池,则可以。感谢您提供的所有信息,现在我正在阅读您发布的所有文档,以了解如何更好地管理http连接,并尝试新的方法。我需要一些时间来处理一切。
    ServicePointManager.DefaultConnectionLimit = 500;
    // if you can get collection of most scrapped ones:
    var domains = new [] { "http://slowwly.robertomurray.co.uk" };
    foreach(var d in domains)
    {
        var delayServicePoint = ServicePointManager.FindServicePoint(new Uri(d));
        delayServicePoint.ConnectionLimit = 10; // or bigger
    }