【发布时间】:2015-03-20 18:00:46
【问题描述】:
还有一个关于yield return的问题
所以我需要远程执行不同的 SQL 脚本。脚本在 TFS 中,所以我会自动从 TFS 获取它们,并且该过程会遍历所有文件,读取它们在内存中的内容并将内容发送到远程 SQL 服务器。
到目前为止,该过程完美无缺。但现在一些脚本将包含bulk inserts,将脚本的大小增加到 500,000 MB 或更多。
所以我构建了代码“thinking”,我曾经在内存中读取文件的内容,但现在我有了第二个想法。
这就是我所拥有的(过于简化):
public IEnumerable<SqlScriptSummary> Find(string scriptsPath)
{
if (!Directory.Exists(scriptsPath))
{
throw new DirectoryNotFoundException(scriptsPath);
}
var path = new DirectoryInfo(scriptsPath);
return path.EnumerateFiles("*.sql", SearchOption.TopDirectoryOnly)
.Select(x =>
{
var script = new SqlScriptSummary
{
Name = x.Name,
FullName = x.FullName,
Content = File.ReadAllText(x.FullName, Encoding.Default)
};
return script;
});
}
....
public void ExecuteScripts(string scriptsPath)
{
foreach (var script in Find(scriptsPath))
{
_scriptRunner.Run(script.Content);
}
}
我的理解是EnumerateFiles 将yield return 一次处理每个文件,所以这就是让我“认为”我在内存中一次加载一个文件的原因。
但是……
一旦我对它们进行迭代,在 ExecuteScripts 方法中,在 foreach 循环中使用的 script 变量退出后会发生什么情况范围?那是处置吗?还是留在记忆中?
如果它保留在内存中,这意味着即使当我使用迭代器并在内部使用
yield return时,当我遍历所有它们时它们仍然在内存中,对吗?所以最后它就像使用ToList只是懒惰执行,对吗?如果
script变量在超出范围时被释放,那么我想我会没事的
如何重新设计代码以优化内存消耗,例如强制一次将脚本的内容加载到内存中
其他问题:
如何测试(单元/集成测试)我在内存中一次只加载一个脚本?
如何测试(单元/集成测试)每个脚本是否已从内存中释放/未从内存中释放?
【问题讨论】:
标签: c# memory memory-management iterator yield-return