另一个如何释放内存的问题:
我正在两个当前相同但很快就会不同步的数据库之间复制数据。我使用 Reflection 和 ADO.Net Entities 在 C# 中编写了一个框架应用程序,它执行以下操作:
对于源数据库中的每个表:
- 清除目标数据库中的对应表
- 对于源表中的每个对象
- 对于源对象中的每个属性
- 如果目标对象中存在同名属性,则使用反射将源属性复制到目标属性
- 对于源对象中的每个属性
在我找到包含用户上传文件的 900MB 大表之前,这非常有效。
将 blob(每个最多 7 MB)复制到我的机器并返回到目标数据库的过程会占用本地内存。但是,该内存没有被释放,一旦复制了大约 750 MB 的数据,该进程就会终止——当抛出 OutOfMemoryException 时,我的程序有 1500 MB 的分配空间,大概是到目前为止它复制的所有内容的两个副本。
我先尝试了一种天真的方法,做了一个简单的复制。它在每张桌子上都有效,直到我拿到大桌子为止。我曾尝试强制 aGC.Collect()
对结果没有明显变化。我还尝试将实际副本放入一个单独的函数中,希望超出范围的引用有助于它获得 GC。我什Thread.Sleep
至尝试让后台进程有更多时间运行。所有这些都没有效果。
这是目前存在的相关代码:
public static void CopyFrom<TSource, TDest>(this ObjectSet<TDest> Dest, ObjectSet<TSource> Source, bool SaveChanges, ObjectContext context)
where TSource : class
where TDest : class {
int total = Source.Count();
int count = 0;
foreach (var src in Source) {
count++;
CopyObject(src, Dest);
if (SaveChanges && context != null) {
context.SaveChanges();
GC.Collect();
if (count % 100 == 0) {
Thread.Sleep(2000);
}
}
}
}
我没有包含 CopyObject() 函数,它只是使用反射来评估 src 的属性并将它们放入要附加到 Dest 的新对象中的同名属性中。
SaveChanges 是传入的布尔变量,表示应该进行此额外处理,仅在大表上为 true,否则为 false。
所以,我的问题是:如何修改此代码以不让我内存不足?