我正在使用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',因为它正被另一个进程使用。”
答案 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);
}