简体   繁体   English

NamedScopes Ninject绑定和异步(线程)

[英]NamedScopes Ninject bindings and async (threading)

My project is structured by services and repositories (all repositories share the db context). 我的项目由服务和存储库构成(所有存储库共享数据库上下文)。 In one of my service layers, I have an asynchronous method that writes to the database using a repository. 在我的一个服务层中,我有一个使用存储库写入数据库的异步方法。 The web request will finish and dispose of the context before this method can get to use it. 在此方法可以使用之前,Web请求将完成并处理上下文。 I tried to understand NamedScopes as stated in this answer . 我试图理解这个答案中所述的NamedScopes I still can't seem to understand how to implement it. 我似乎还无法理解如何实现它。 I'll show how my project is structured and hope someone can help me at the code level. 我将展示我的项目是如何构建的,并希望有人可以在代码级别帮助我。

Bindings 绑定

    private static void RegisterServices(IKernel kernel)
    {
        //dbcontext
        kernel.Bind<EntityDatabaseContext>().ToMethod(context => new EntityDatabaseContext()).InRequestScope();

        //unit of work
        kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();

        //repositories
        kernel.Bind<IRepository<Account>>().To<Repository<Account>>().InRequestScope();

        //services
        kernel.Bind<IAuthenticationService>().To<AuthenticationService>().InRequestScope();
    }

AuthenticationService uses constructor injection AuthenticationService使用构造函数注入

public AuthenticationService(UnitOfWork unitOfWork, IRepository<Account> accountRepository){}

A method inside my AuthenticationService 我的AuthenticationService中的一个方法

    //this is a background process
    public Task SomeMethodAsync(string text)
    {
        //spin it off into a new task
        return Task.Factory.StartNew(() => SomeMethod(text));
    }

SomeMethod makes use of accountRepository . SomeMethod使用accountRepository Please tell me if anymore information is needed. 如果需要更多信息,请告诉我。 Please help me with the threading issue, if NamedScopes is the solution, how do I implement it in my case? 请帮我解决线程问题,如果NamedScopes是解决方案,我该如何在我的情况下实现它?

Basically, a background process is being executed and it is using a context that is being disposed of by ninject due to the request scope. 基本上,正在执行后台进程,并且它正在使用由于请求范围而由ninject处理的上下文。

You should be aware that running background threads can cause you many problems. 您应该知道运行后台线程可能会导致许多问题。 IIS can decide to recycle the app pool at any time which will terminate your thread immediately (or it doesn't execute in some cases at all) leaving your application in an inconsistent state. IIS可以随时决定回收应用程序池,这将立即终止您的线程(或者在某些情况下根本不执行),使您的应用程序处于不一致状态。

http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx

The easiest and least error prone wayto run asyncronous operations is to implement a windows service and delegate those async operations to the windows service eg using MSMQ. 运行异步操作的最简单且最不容易出错的方法是实现Windows服务并将这些异步操作委托给Windows服务,例如使用MSMQ。

If you still want to go the hard way then read about HostingEnvironment.RegisterObject and IRegisteredObject to prevent these inconsistent situations. 如果你仍然想要努力,那么请阅读HostingEnvironment.RegisterObjectIRegisteredObject以防止这些不一致的情况。

The Ninject part is quite easy. Ninject部分非常简单。 Just create some job processor class eg MyJobProcessor taking all required dependencies to execute the task. 只需创建一些作业处理器类,例如MyJobProcessor获取所有必需的依赖项来执行任务。 It should implement INotifyWhenDisposed . 它应该实现INotifyWhenDisposed The easiest way to do so is to derive from DisposeNotifyingObject . 最简单的方法是从DisposeNotifyingObject派生。

public class MyJobProcessor : DisposeNotifyingObject, IRegisteredObject
{
    public void Execute() { ... }
    public void Stop(bool immediate) { ... }
}

Inject this processor to the controller and let the Task start it and dispose it when it has finished its work. 将此处理器注入控制器,然后让Task启动它并在完成工作后将其处理掉。

Task.Factory.StartNew(() => 
    { 
        try 
        { 
            processor.Execute(); 
        } 
        finally 
        { 
            processor.Dispose); 
        }
    });

Specify that it is the scope for its dependencies. 指定它是其依赖项的范围。

Bind<MyJobProcessor>().ToSelf().Named("MyJobProcessor").DefinesNamedScope("MyJobProcessorScope");
Bind<IUnitOfWork>().To<UnitOfWork>().WhenAnyAnchestorNamed("MyJobProcessor").InNamedScope("MyJobProcessorScope");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM