首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >调用IEnumerable.Count()需要多秒时间

调用IEnumerable.Count()需要多秒时间
EN

Stack Overflow用户
提问于 2019-10-02 20:50:42
回答 2查看 468关注 0票数 5

我已经创建了一个小窗口服务,它应该删除某些文件夹中某个文件名的所有出现。所有这些代码都运行在计时器的elapsed-handler (intervall=10s)中。

当服务运行时,我可以识别出该服务使用的CPU增加了20%,所以我检查了我的代码,在其中放置了一些跟踪命令,发现执行处理程序花费了大约3-4秒的时间。

我将其缩小到以下代码段:allReporterFiles.Count()。它调用这个IEnumerable的方法IEnumerable,这个调用需要3-4秒。

我的项目是为.NET 4.7.2设置的。这是框架错误还是什么?

代码语言:javascript
复制
 var files1 = Directory.EnumerateFiles(dirSwReporter, swReporterFileName, SearchOption.AllDirectories);
 var files2 = Directory.EnumerateFiles(dirSwReporter2, swReporterFileName, SearchOption.AllDirectories);

 var allReporterFiles = files1.Union(files2);

 var sw = Stopwatch.StartNew();
    var fileCount = allReporterFiles.Count(); // <--- takes ~3.5 seconds
 sw.Stop();

 Trace.WriteLine($"KillChromeSoftwareReporterTool completed in: {sw.Elapsed.TotalMilliseconds}ms or  {sw.Elapsed.TotalSeconds}sec");
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-10-02 20:56:06

这是框架错误还是什么?

这是一个问题,你理解LINQ的延迟执行,我怀疑。

allReporterFiles只是一个IEnumerable<string>。调用Count()意味着迭代它-这反过来意味着Union代码在files1files2上迭代。我怀疑你有很多文件。

判断这一点的方法是度量分别在files1files2上迭代所需的时间。一个简单的方法是调用ToList()。例如:

代码语言:javascript
复制
// The use of ToList forces the result to be materialized, rather than using deferred
// execution.

var stopwatch = Stopwatch.StartNew();
var files1 = Directory
    .EnumerateFiles(dirSwReporter, swReporterFileName, SearchOption.AllDirectories)
    .ToList();
var files1Time = stopwatch.Elapsed;

stopwatch.Restart();
var files2 = Directory
    .EnumerateFiles(dirSwReporter2, swReporterFileName, SearchOption.AllDirectories)
    .ToList();
var files2Time = stopwatch.Elapsed;

然后记录files1Timefiles2Time。现在,内容在两个列表中,计数Union将不涉及任何IO。为了避免不止一次地返回相同的值,它仍然需要按原样创建一个HashSet<string>,但是它会更快,更快。

这种方法在总体上不会更快--而且会使用更多内存--但它会让人清楚地知道,大多数时间是在dirSwReporter还是dirSwReporter2中搜索,这可能足以帮助您进行优化。

票数 12
EN

Stack Overflow用户

发布于 2019-10-02 22:26:36

关于延迟执行的信息隐藏在.NET Framework4.7Directory.EnumerateFiles法的doco的备注部分中。

EnumerateFilesGetFiles方法的不同之处如下:使用EnumerateFiles时,可以在返回整个集合之前开始枚举名称集合;使用GetFiles时,必须等待返回整个名称数组后才能访问该数组。因此,当您处理许多文件和目录时,EnumerateFiles可以更高效。

关于效率的部分显然与上下文无关,因为您正在对结果调用Count,这需要完整的枚举。

顺便说一下。.NET Framework4.8Directory.EnumerateFiles法的doco声明:

返回的集合不被缓存;每次对集合上的GetEnumerator调用都将启动一个新的枚举。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58209175

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档