线程队列进程

时间:2013-07-05 16:12:46

标签: c# multithreading queue

我正在使用C#.Net4.0在visual studio 2010中构建此程序 目标是使用线程和队列来提高性能。

我有一个我需要处理的网址列表。

string[] urls = { url1, url2, url3, etc.} //up to 50 urls

我有一个函数,它将接收每个URL并处理它们。

public void processUrl(string url) { 
    //some operation
}

最初,我创建了一个for循环来遍历每个网址。

for (i = 0; i < urls.length; i++)
    processUrl(urls[i]);

该方法有效,但程序很慢,因为它一个接一个地通过网址。

所以我的想法是使用线程来减少时间,但我不太清楚如何处理它。

假设我想创建5个线程来同时处理。

当我启动程序时,它将开始处理前5个URL。当一个完成后,程序开始处理第6个URL;当另一个完成时,程序开始处理第7个网址,依此类推。

问题是,我不知道如何实际创建网址的“队列”并能够通过队列和进程。

任何人都可以帮我吗?

- 下午1:42编辑 -

当我同时运行5个进程时,我遇到了另一个问题。

processUrl函数涉及写入日志文件。如果多个进程同时超时,它们会同时写入同一个日志文件,我认为这会引发错误。

我假设这是问题所在,因为我收到的错误消息是“进程无法访问文件'data.log',因为它正被另一个进程使用。”

3 个答案:

答案 0 :(得分:2)

最简单的选择就是使用Parallel.ForEach。如果processUrl是线程安全的,您可以写:

Parallel.ForEach(urls, processUrl);

我不建议限制为5个线程(调度程序会自动正常扩展),但这可以通过以下方式完成:

Parallel.ForEach(urls, new ParallelOptions { MaxDegreeOfParallelism = 5}, processUrl);

话虽如此,URL处理本质上通常是IO绑定的,而不是CPU绑定的。如果您可以使用Visual Studio 2012,则更好的选择是重新设置此选项以使用该语言中的新async支持。这需要将您的方法更改为更像:

public async Task ProcessUrlAsync(string url)
{
    // Use await with async methods in the implementation...

然后,您可以在循环中使用新的async支持:

// Create an enumerable to Tasks - this will start all async operations..
var tasks = urls.Select(url => ProcessUrlAsync(url));

await Task.WhenAll(tasks); // "Await" until they all complete

答案 1 :(得分:1)

使用并行Foreach并将最大并行度设置为您想要的线程数(或将其留空并让.NET为您工作)

ParallelOptions parallelOptions = new ParallelOptions();

parallelOptions.MaxDegreeOfParallelism = 5;
Parallel.ForEach(urls, parallelOptions, url =>
{
   processUrl(url);
});

答案 2 :(得分:0)

如果你真的想创建线程来完成任务而不是使用并行执行:

假设我想为每个网址添加一个帖子:

string[] urls = {"url1", "url2", "url3"};

我只为每个网址(或每个网址)启动一个新的Thread实例:

foreach (var thread in urls.Select(url => new Thread(() => DownloadUrl(url))))
    thread.Start();

下载网址的方法:

private static void DownloadUrl(string url)
{
    Console.WriteLine(url);   
}