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

时间:2016-02-04 12:04:24

标签: c# multithreading

我有一个URL列表,我必须调用它并做一些工作。这已经可以正常工作,但List很大,执行时间很长。

我认为我可以通过同时处理5个Url来加速程序,因为执行时间的很大一部分很可能是程序正在等待Urls服务器响应。

我有一个网址列表

List<string> urls = getmyurls();

然后我正在迭代它们

for (int i = 0; i < links.Count; i++)
{
    List<string> result = dosomework(urls.ElementAt(i))
    urls.AddRange(result);
}

有时我会收到一些必须处理的额外网址。

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

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

另外:你会运行多少个线程?

3 个答案:

答案 0 :(得分:1)

当您尝试解析URL并从网络中拔出时,它类似于从磁盘拉出或从数据库读取,因为这些都是I / O绑定操作。并行实际上是不可取的,因为更多的线程没有帮助,而是阻碍性能。您最好的选择是使用asyncawait关键字,假设您使用 .NET 4.5

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

关于执行I / O绑定异步操作的

Here is great video demonstration作者:Jeffrey Richter。我强烈鼓励观看它。与此同时,我会编写你的迭代调用。

    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上执行的任务。然后等待所有这些。

<强>更新

看起来似乎已经回答了限制here

答案 1 :(得分:0)

我是TPL Dataflow library的粉丝。它完全符合这个用例,值得学习。

这是一个原始实现,向您展示它的工作原理。

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();

可以阅读流程管道的一个很好的例子here

答案 2 :(得分:-1)

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

考虑https://msdn.microsoft.com/pl-pl/library/dd460714(v=vs.110).aspx

中的示例

编辑: 在多个线程上运行时,添加WithDegreeOfParallelism(6),其中6是“线程”计数。这不完全是6个线程但是你想要的:) 在这里你有一个很好的解释:http://www.albahari.com/threading/part5.aspx

另外 ParallelOptions.MaxDegreeOfParallelism指定最大并行级别