C# 五个线程处理任务列表c

C# 五个线程处理任务列表c,c#,multithreading,C#,Multithreading,我有一个URL的列表,我必须调用和做一些工作。这已经可以很好地工作了,但是列表非常大,执行时间非常长 我想我可以通过同时处理5个URL来加快程序的速度,因为大部分的执行时间可能是程序等待URL服务器响应 我有一个URL列表 List<string> urls = getmyurls(); 然后我会反复浏览它们 for (int i = 0; i < links.Count; i++) { List<string> result = dosomework(u

我有一个URL的列表,我必须调用和做一些工作。这已经可以很好地工作了,但是列表非常大,执行时间非常长

我想我可以通过同时处理5个URL来加快程序的速度,因为大部分的执行时间可能是程序等待URL服务器响应

我有一个URL列表

List<string> urls = getmyurls();
然后我会反复浏览它们

for (int i = 0; i < links.Count; i++)
{
    List<string> result = dosomework(urls.ElementAt(i))
    urls.AddRange(result);
}
有时我会得到一些额外的URL返回,必须处理太多

代码就是一个例子,我的实际程序的结构有点不同。这是解释我的问题的一个最小的例子

我想要的是五个线程同时运行dosomework函数。每当其中一个完成时,我希望它从下一个URL开始


另外:您将运行多少个线程?

您正在寻找的可能是并行LINQ

请考虑以下例子:

编辑: 对于在多个线程上运行,可以使用degreeofparallelism6添加,其中6是线程数。这不完全是6个线程,但正是您想要的: 这里有一个很好的解释:


ParallelOptions.MaxDegreeOfParallelism指定最大并行级别

当您尝试解析URL并从网络中提取时,与从磁盘提取或从数据库读取类似,因为这些都是I/O绑定的操作。实际上,并行是不可取的,因为更多的线程无助于提高性能,反而会阻碍性能。假设您使用的是.NET4.5,那么最好使用async和await关键字

有些人建议使用Parallel.ForEach,但这最适合CPU受限的任务。对于I/O绑定的任务,您需要Task.WhenAll

Jeffrey Richter关于执行I/O绑定异步操作的文章。我强烈鼓励观看。同时,我会像这样编写迭代调用

    private static IEnumerable<string> GetUrls()
    {
        return new[] { "https://stackoverflow.com/", "http://www.google.com/" };
    }

    internal async Task Fetch()
    {
        var urls = GetUrls();
        var tasks = urls.Select(DoWorkAsync);
        await Task.WhenAll(tasks);
    }

    internal Task DoWorkAsync(string url)
    {
        // TODO: Implement actual work on the URL in an async manner.
        return Task.FromResult(url);
    }  
其思想是,您可以获取URL,并从每个URL中选择一个在DoWorkAsync上执行的任务。所有这些都在等待

更新

似乎节流问题已经得到了解决。

我是这方面的超级粉丝。它完全符合这个用例,值得学习

下面是一个原始实现,向您展示它是如何工作的

var processURL = new TransformManyBlock<string, string>(url => {
    return dosomework(url);
},
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 5 });

var urls = getmyurls();
foreach(var url in urls)
    processURL.Post(url);

processURL.Completion.Wait();
var results = processURL.Receive();

可以阅读一个很好的流程管道示例。

尝试搜索。并行taks库。如果你想走得快,放弃你的简单想法,即线程越多,速度就越快。学习如何进行异步IO而不是阻塞IO。正如CodeCaster提到的,TPL是一个很好的起点。它将为您确定并行运行的任务数量等。对于跳转到并行foreach是非常简单的。您肯定想看看,但不会一次执行所有我的URL。如何确定一次允许使用多少Parrelell线程?我想我可以通过同时处理5个URL来加快程序的速度,我明白这是你想要的:也许我不完全理解。我想对所有URL执行我的函数,但一次只能执行5个。每当我完成一个链接时,我想从下一个开始。好的,假设你有一些实际的CPU限制的任务来处理这些链接,我写的东西实际上可能会帮助你。考虑这个例子:假设你有大量的数字列表,你想为每个人计算SqRT。您可以从test2中的项选择Math.Sqrtitem.ToArray来执行这个变量querySequential=from。要使其并行,只需将其更改为:var queryParallel=from test2.AsParallel.AsOrdered.WithDegreeOfParallelism5选择Math.Sqrtitem.ToArray我已经检查过了,并行大约比顺序快3倍,所以它可以工作:当然是一次计算5次谢谢,这真的很难理解,而且会非常明确地尝试一下,但在这种特殊情况下,我有一个问题,即任务的结果可能会向队列中添加其他任务。这将很难在这里合并。但是我如何知道或影响同时调用多少个URL呢。看起来程序正在尽快调用所有的URL。这是一个不同的问题,我回答了原文。我可以想象,如果列表可能很大,您可以实现某种类型的缓冲区或队列,然后每次批调用N。这就是最初的问题。名单非常庞大。最初超过1000个URL,每个任务可能会添加更多的URL。这似乎解决了问题。尽管我没有时间去尝试。谢谢,我相信async+TPL数据流是一个不错的选择。