2012-07-29 87 views
5

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

绑定

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处理的上下文。

+1

请您详细说明您想实现的目标吗?你只是想要异步地在你的方法SomeMethodAsync中加载一些数据,或者你想在后台处理一些像时尚这样的工作中的信息吗? 您的设计中的一个主要问题是,您正在直接启动SomeMethodAsync中的新任务。开始一项新任务并不能保证任务的执行。任务可能会在您的请求结束后执行,然后ninject已经在请求范围内处理完毕。如果您使用AsyncController,则应该在其上注册该任务。但是API不应该启动它 – 2012-07-30 15:01:54

+0

@DanielMarbach这是我的问题,任务可能在请求结束并且ninject处理上下文之后执行。我需要告诉ninject等待。不知道如何做到这一点。 – 2012-07-30 17:37:51

+0

@DanielMarbach你是什么意思API不应该启动它? – 2012-07-30 17:38:56

回答

6

您应该知道运行后台线程会导致很多问题。 IIS可以随时决定回收应用程序池,这会立即终止您的线程(或者根本不执行),导致应用程序处于不一致的状态。

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

的最简单和最容易出错京顺路运行asyncronous操作是实现一个Windows服务和委派那些异步操作的窗口服务例如使用MSMQ。

如果您仍然想要努力学习,请阅读HostingEnvironment.RegisterObjectIRegisteredObject以避免这些不一致的情况。

Ninject部分非常简单。只需创建一些作业处理器类MyJobProcessor采取所有必需的依赖关系来执行任务。它应该执行INotifyWhenDisposed。最简单的方法是从DisposeNotifyingObject派生。

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

将此处理器注入控制器,让任务启动并在完成工作后进行处置。

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

指定它是其依赖项的范围。

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

谢谢,关于使用Windows服务,它适用于像日志记录(用户登录,我登录)或发送电子邮件(模板)?这些行为使得行动需要更长时间才能返回,这就是为什么我希望他们在后台任务中。 – 2012-08-06 03:21:33

+0

@Lolcoder问题是你是否可以承担失去这些数据。例如。如果服务器由于某些错误而回收,您是否可以承受没有日志?或者你可以生活在没有发送电子邮件的情况下吗?记录和发送电子邮件通常不需要依赖关系。你还应该检查你真正获得了多少表现。创建和启动任务也需要一些时间。 – 2012-08-06 14:19:32

+0

如果其中任何一个都是在请求中同步完成的,并且池回收也不会失败? – solipsicle 2016-05-17 23:34:26