さらに別のメモリを解放する方法の質問:
現在同一である2つのデータベース間でデータをコピーしていますが、間もなく同期がとれなくなります。これを行うReflectionとADO.Netエンティティを使用してC#でスケルトンアプリをまとめました。
ソースデータベースのテーブルごとに:
- 宛先データベースの対応するテーブルをクリアします
- ソーステーブルのオブジェクトごと
- ソースオブジェクトのプロパティごとに
- 同じ名前のプロパティが宛先オブジェクトに存在する場合は、Reflectionを使用してソースプロパティを宛先プロパティにコピーします
- ソースオブジェクトのプロパティごとに
これは、ユーザーがアップロードしたファイルが含まれている大きな900MBのテーブルに到達するまではうまく機能します。
ブロブ(それぞれ最大7 MB)を自分のマシンにコピーして宛先データベースに戻すプロセスは、ローカルメモリを使い果たします。ただし、そのメモリは解放されておらず、約750 MB相当のデータがコピーされると、プロセスは停止します。OutOfMemoryExceptionがスローされたときにプログラムに1500 MBの割り当てられたスペースがあり、おそらくこれまでにコピーされたすべてのコピーが2つあります。
私は最初に単純なコピーをして、素朴なアプローチを試みました。私が大きなテーブルにたどり着くまで、それはすべてのテーブルで機能しました。GC.Collect()
結果に明らかな変化を与えることなく、強制的にaを試してみました。また、スコープ外の参照が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です。
だから、私の質問:メモリが不足しないようにこのコードを変更するにはどうすればよいですか?