应用程序解析某个目录中的文件,同时将新文件添加到目录中。我使用 ConcurrentQueue 并尝试将工作分配给核心数。因此,如果有文件要处理 - 它应该同时处理最多 4 个(核心)文件。 然而,在处理 10-30 个文件后,该应用程序会在几秒钟内运行 OOM。我看到内存消耗迅速增长到 ~1.5GB,然后出现 OOM 错误。 我是任务调度程序,所以我可能做错了什么。 文件解析是通过在文件上运行一些 .exe 来完成的,它使用 <5mb 或 ram。 任务调度程序在每次计时器线程结束时运行。但是它甚至在计时器第二次超时之前就运行了 OOM。
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
DirectoryInfo info = new DirectoryInfo(AssemblyDirectory);
FileInfo[] allSrcFiles = info.GetFiles("*.dat").OrderBy(p => p.CreationTime).ToArray();
var validSrcFiles = allSrcFiles.Where(p => (DateTime.Now - p.CreationTime) > TimeSpan.FromSeconds(60));
var newFilesToParse = validSrcFiles.Where(f => !ProcessedFiles.Contains(f.Name));
if (newFilesToParse.Any()) Console.WriteLine("Adding " + newFilesToParse.Count() + " files to the Queue");
foreach (var file in newFilesToParse)
{
FilesToParseQueue.Enqueue(file);
ProcessedFiles.Add(file.Name);
}
if (!busy)
{
if (FilesToParseQueue.Any())
{
busy = true;
Console.WriteLine("");
Console.WriteLine("There are " + FilesToParseQueue.Count + " files in queue. Processing...");
}
var scheduler = new LimitedConcurrencyLevelTaskScheduler(coresCount); //4
TaskFactory factory = new TaskFactory(scheduler);
while (FilesToParseQueue.Any())
{
factory.StartNew(() =>
{
FileInfo file;
if (FilesToParseQueue.TryDequeue(out file))
{
//Dequeue();
ParseFile(file);
}
});
}
if (!FilesToParseQueue.Any())
{
busy = false;
Console.WriteLine("Finished processing Files in the Queue. Waiting for new files...");
}
}
}
最佳答案
只要有文件要处理,您的代码就会不断创建新的Task
,而且它的速度要快得多,以至于可以处理文件。但它没有其他限制(如目录中的文件数),这就是它很快耗尽内存的原因。
一个简单的解决方法是将出列移到循环之外:
while (true)
{
FileInfo file;
if (FilesToParseQueue.TryDequeue(out file))
{
factory.StartNew(() => ParseFile(file));
}
else
{
break;
}
}
如果您只为每个内核创建一个 Task
并在这些 Task
中使用循环处理文件,您将获得更好的性能。
关于c# - 使用任务计划程序的应用程序很快就会耗尽内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35352808/