6

私はEntityFramework、バックグラウンドジョブクラスの束で汎用リポジトリと作業単位パターンを使用および実装しています。ジョブ クラスは Unity DI を使用して作成されるため、ほとんどがリポジトリとUnitOfWorkオブジェクトである依存関係を注入できます。リポジトリと作業単位は EF を共有する必要がありDbContextます。

一般的なジョブは次のようになります。

public class CommonJob : IJob, IDisposable
{        
    private IRepo<SomeEntity> _repo;
    private IUnitOfWork _uow;

    public CommonJob(IRepo<SomeEntity> repo, IUnitOfWork uow)
    {
        _repo = repo;
        _uow = uow;
    }

    public void RunJob()
    {
        // do stuff here
    }

    public void Dispose()
    {
        _uow.Commit();
        _uow.Dispose();
    }
}

すべてのジョブは、次のような新しいタスク内で実行されます

Task.Factory.StartNew(() => {
    // container is UnityContainer
    var job = container.Resolve<CommonJob>();
    job.RunJob();
    job.Dispose();
});

そして、Unity を使用して作業単位とリポジトリを Unity に登録しました。これPerThreadLifetimeManagerにより、登録されたインスタンスを 1 つのタスクのコンテキスト内 (およびその 1 つのジョブ オブジェクト内) で共有できるが、外部では共有できないと考えました。

私が抱えている問題は、破棄されたオブジェクトがジョブに挿入されることがありますが、これは明らかにあまり良くありません。Task.Factory.StartNew()常に新しいスレッドを使用するとは限らないことを読んでいます。PerThreadLifetimeManagerこれは、がタスク間でオブジェクトを共有するということですか? これが本当なら、実行中のスレッドに関係なく、各タスクが分離して動作できるようにする、オブジェクトのリフトタイムを統一して管理する別の方法はありますか?

編集:

以下の選択された回答は同じことを達成しますが、HierarchicalLifetimeManager各ジョブの依存関係の分離を達成するために、子コンテナーを使用することになりました。

次に例を示します。

// registering the dependencies, 
// these should be singletons, but only within the context of one job
_container.Register(typeof(IRepo<>), typeof(Repo<>), new HierarchicalLifetimeManager())
          .Register<IUnitOfWork, UnitOfWork>(new HierarchicalLifetimeManager());

// starting a new job
Task.Factory.StartNew<IUnityContainer>(() => 
{
    // create a child container to remove instance sharing between tasks
    var childContainer = _container.CreateChildContainer();

    // figure out and resolve the job class from the child container
    // this will make sure that different jobs do not share instances
    var jobType = GetJobType();
    var job = childContainer.Resolve(jobType) as IJob;

    job.RunJob();

    return childContainer;
}).ContinueWith(previousTask => {
    // when the job is done, dispose of the child container
    task.Result.Dispose(); 
});
4

1 に答える 1

6

並列ライブラリはスレッド プールを使用し、Unity はプールの同じスレッドに対して同じオブジェクトを返すため、破棄されたオブジェクトを取得します。

投稿した方法でコンテナーを使用する場合は、PerResolveLifetimeManagerを使用することをお勧めします。このように、オブジェクトを解決すると、解像度グラフ全体が同じインスタンスを共有しますが、インスタンスは解像度ごとに一意になります。各タスクは、 を呼び出すときに独自のインスタンスを持ちますResolve

于 2013-08-19T09:37:44.727 に答える