【问题标题】:NamedScopes Ninject bindings and async (threading)NamedScopes Ninject 绑定和异步(线程)
【发布时间】:2012-07-29 16:57:31
【问题描述】:

我的项目由服务和存储库构成(所有存储库共享数据库上下文)。在我的一个服务层中,我有一个使用存储库写入数据库的异步方法。 Web 请求将在此方法开始使用之前完成并处理上下文。我试图理解NamedScopes,正如answer 中所述。我似乎仍然无法理解如何实现它。我将展示我的项目的结构,并希望有人可以在代码级别帮助我。

绑定

    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 使用构造函数注入

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

我的 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 使用accountRepository。请告诉我是否需要更多信息。请帮助我解决线程问题,如果 NamedScopes 是解决方案,我该如何实现它?

基本上,一个后台进程正在执行,并且由于请求范围,它正在使用由 ninject 处理的上下文。

【问题讨论】:

  • 您能否详细说明您想要实现的目标?您只是想在您的方法 SomeMethodAsync 中异步加载一些数据,还是想以类似方式的工作在后台处理一些信息?您设计中的一个主要问题是,您直接在 SomeMethodAsync 中开始一项新任务。开始一个新任务并不能保证任务的执行。这些任务可能会在您的请求结束后执行,然后 ninject 将已经在请求范围内处理。如果您使用 AsyncController,则应在其上注册任务。但是 API 不应该启动它
  • @DanielMarbach 这是我的问题,该任务可能会在请求结束并 ninject 处理上下文后执行。我需要告诉ninject 等待。不知道该怎么做。
  • @DanielMarbach 你是什么意思 API 不应该启动它?
  • 关于开始:我错了。 TPL 指南声明您必须启动该任务。所以那个很好。在我看来,这个问题与ninject无关。您需要使用 AsyncController 并使用异步控制器进行异步操作。那么它应该可以工作了。
  • 你想达到什么目的?您是希望在任务启动后立即完成 Web 请求,还是希望请求等待任务的某些结果,以便您可以从该结果中返回一些信息?

标签: c# asp.net-mvc ninject


【解决方案1】:

您应该知道,运行后台线程可能会给您带来很多问题。 IIS 可以随时决定回收应用程序池,这将立即终止您的线程(或者在某些情况下根本不执行),从而使您的应用程序处于不一致的状态。

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

运行异步操作的最简单和最不容易出错的方法是实现一个 Windows 服务并将这些异步操作委托给 Windows 服务,例如使用 MSMQ。

如果您仍想坚持到底,请阅读 HostingEnvironment.RegisterObjectIRegisteredObject 以防止出现这些不一致的情况。

Ninject 部分非常简单。只需创建一些作业处理器类,例如MyJobProcessor 获取执行任务所需的所有依赖项。它应该实现INotifyWhenDisposed。最简单的方法是从DisposeNotifyingObject 派生。

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

将这个处理器注入控制器,让Task启动它,并在它完成工作后处理它。

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

指定它是其依赖项的作用域。

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

【讨论】:

  • 谢谢,关于使用windows服务,是否适合登录(用户登录,我登录)或发送电子邮件(模板)之类的情况?这些行为使操作需要更长的时间才能返回,这就是我希望它们在后台任务中的原因。
  • @Lolcoder 问题是你是否能承受丢失这些数据的代价。例如。如果服务器由于某些错误而回收,你能承受没有日志吗?或者你能忍受不发送电子邮件的情况吗?此外,记录和发送电子邮件通常不需要依赖项。您还应该检查您真正获得了多少性能。创建和启动任务也需要一些时间。
  • 如果其中任何一个在请求中同步完成并且池被回收,它们不会也失败吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-14
  • 1970-01-01
  • 2013-06-20
  • 1970-01-01
  • 2010-09-26
  • 1970-01-01
相关资源
最近更新 更多