【发布时间】:2017-02-04 18:10:38
【问题描述】:
我想同时抓取几个网站,但只是将信息一个一个添加到数据库中。同时我的代码看起来与此类似:
List<SiteMetadata> sitesList = GetSites();
var tasks = new List<Task<SiteMetadata>>();
foreach (var item in sitesList)
tasks.Add(item.LoadMetaDataAsync());
int totalSites = sitesList.Count;
int finishedSites = 0;
int errors = 0;
while (totalSites != finishedSites)
{
var tempSite = await Task.WhenAny(tasks.ToArray());
//WRITE HERE TO DB!!!!!!!!!!!!!!!!!
tasks.Remove(tempSite);
var tempLog = apiHandler.WriteToDatabase(tempSite.Result);
if (tempLog.Type == LogType.Error)
{
errors++;
LogsHandler.AddToLog(tempLog);
}
finishedSites++;
}
我要的是提高这里的效率并替换掉:
var tasks = new List<Task<SiteMetadata>>();
foreach (var item in sitesList)
tasks.Add(item.LoadMetaDataAsync());
到这样的事情:
var runAll = Task.Factory.StartNew(() => Parallel.ForEach(sitesList, item => item.LoadMetaDataAsync()));
但问题是我不知道如何将完成的第一个任务逐个获取到数据库。无论如何,使用 Parallel 或类似的东西,甚至比我现在正在做的更有效的东西来做到这一点? 提前致谢。
【问题讨论】:
-
您可以尝试实现一个在
LoadMetaDataAsync末尾触发的事件。此事件将在任务完成时通知您。那么你只需要用你的数据填充你的数据库到事件处理函数中 -
在异步操作中抛出更多线程无济于事。您不受核心数量的限制,无论如何您都受到网络的限制。异步方法(正确编写时)立即产生控制。
-
我在您发布的代码中没有看到任何暗示您的提案会“提高效率”,甚至与您所拥有的一样好现在。如果您认为可以,请提供一个良好的 minimal reproducible example,它可以可靠地重现您现在遇到的效率问题,解释该问题是什么,以及为什么您认为可以采取一些措施来改进它。
标签: c# .net task-parallel-library task c#-5.0