NCron を使用していくつかのジョブを定期的に実行する Windows サービスがあります。私は最近 Ninject を導入しましたが、EF コンテキスト (EF4.1 の ObjectContext) が GC されていない (メモリ プロファイルを作成した) ため、重大なメモリの問題が発生しました。
これらのジョブの一部は非常に長時間 (10 ~ 15 分) 実行され、データベースを集中的に使用することに注意してください。EF がおそらくこの種の作業に最適なソリューションではないことはわかっていますが、現時点でリファクタリングすることは不可能です。
この件に関してかなりの資料を見つけたので、次のように進めました。
- ジョブ クラスに INotifyWhenDisposed を実装する
- 名前付きスコープで EF コンテキスト バインディングを定義しようとしています。ジョブが終了したときに破棄され、適切に GC されることを期待しています。
名前付きスコープが存在しないという ActivationException が発生します。
これを複製するデバッグモードで試した簡単なコードを次に示します。
const string Scope = "Scope";
kernel.Bind(c => c.FromThisAssembly()
.SelectAllClasses().InheritedFrom<MyCronJob>()
.BindToSelf()
.Configure(b => b.DefinesNamedScope(Scope)));
kernel.Bind<IMyContext>().To<MyContext>().InNamedScope(Scope);
kernel.Get<ProcessImportJob>().DoWork();
その後
internal class ProcessImportJob : MyCronJob
{
private readonly IMyContext _ctx;
public ProcessImportJob(IMyContext ctx)
簡潔にするために残りをカットしました。
私は何を間違っていますか?
更新 1 - コンストラクター インジェクションが機能します。明示的.Get<T>
に例外が発生したときです。