解决依赖关系失败,在ActionResult中运行任务

时间:2018-03-16 09:22:02

标签: c# asp.net-mvc dependency-injection task

我需要运行与其他代码并行的繁重代码,以便用户不必等待......我正在尝试Task.Run(() =>来完成我的任务。我的任务是使用依赖注入从服务中调用方法 我收到了以下错误:

  

{“依赖关系的解析失败,输入=   \“Company.CacheProvider.CacheEmployeeProvider \”,name =   \“(无)\”。\ r \ n发生以下情况时发生异常:解析时。\ r \ n \ nException   是:InvalidOperationException - PerRequestLifetimeManager只能   用于HTTP请求的上下文中。可能的原因   错误是在非ASP.NET应用程序上使用生命周期管理器,或   在与相关的线程无关的线程中使用它   同步   上下文。\ r \ n -------------------------------------------- --- \ r \ nAtt   异常时间,容器是:\ r \ n \ r \ n解析   Company.Provider.CacheProvider.CacheEmployeeProvider,(无)\ r \ n   解析构造函数的参数\“cache \”   Company.Provider.CacheProvider.CacheEmployeeProvider(Company.Provider.Interface.IEmployeeProvider   provider,Company.Provider.Interface.ICache cache)\ r \ n解析   Company.Provider.CacheProvider.RequestCache,(none)(映射自   Company.Provider.Interface.ICache,(none))\ r \ n“}

错误提供了可能的原因..但我无法找到解决方案..

整个应用程序正在使用PerRequestLifetimeManager ..如何在may任务中使用它..或者如何让我的任务在不同的上下文中运行而没有任何问题..

更新: - 注册

 var container = new UnityContainer();   

 container.RegisterType<IEmployeeProvider>(new InjectionFactory(unity => unity.Resolve<CacheEmployeeProvider>(new DependencyOverride(typeof(IEmployeeProvider), unity.Resolve<DbEmployeeProvider>()))));       
 container.RegisterType<IEmployeeService, EmployeeService>();

 DependencyResolver.SetResolver(new UnityDependencyResolver(container));
 DynamicModuleUtility.RegisterModule(typeof(Microsoft.Practices.Unity.Mvc.UnityPerRequestHttpModule));

以下是EmployeeController

的基本代码

依赖

[Microsoft.Practices.Unity.Dependency]
public Lazy<IEmployeeService> EmployeeService { get; set; }

发布请求

[HttpPost]
public ActionResult AddEmployee(EmployeeModel model)
{
   var employee = EmployeeService.Value.Add(model);

   Task.Run(() => SetupEmployeeArea(employee.Id)); //task to setup employee related data

   return RedirectToAction("EmployeeList"); //redirect user to the list of employees
}

任务

async Task SetupEmployeeArea(int id)
{
   EmployeeService.Value.EmployeeSetup(id); //this call firing exception
}

我也试过了,但是这段代码并没有完全执行..在调试的时候我把指针丢在了中间而没有发生任何事情。

async Task SetupEmployeeArea(int id)
{
   var employeeService = DependencyResolver.Current.GetService<IEmployeeService>();
   employeeService.EmployeeSetup(id); //not getting any exception and code is also not running
}

请分享建议......或者如果可能的话,请分享最好的替代品以满足我的要求(并行重载代码),除了“Hangfire”..我已经有太多的负担:)

1 个答案:

答案 0 :(得分:2)

问题是http上下文在任务完成之前关闭。尝试使控制器的方法异步并运行如下任务:

await Task.Run(() => SetupEmployeeArea(employee.Id)); //task to setup employee related data

然后任务在http上下文关闭之前完成。

如果您想在任务完成之前返回结果,请考虑使用一些后台工作程序,如QueueBackgroundWorkItem https://blogs.msdn.microsoft.com/webdev/2014/06/04/queuebackgroundworkitem-to-reliably-schedule-and-run-background-processes-in-asp-net/或某些外部框架(如Hangfire),并注册您的依赖项以在http上下文之外解析。

如果在http上下文中不需要解析某些服务,则将其范围更改为另一个,例如瞬态或单身https://msdn.microsoft.com/en-us/library/ff647854.aspx。您始终可以创建自定义生命周期管理器,以便在关闭http上下文时处理案例:https://stackoverflow.com/a/4698138/9502162

另一种方法是加载页面然后使用ajax调用来执行此任务,以便用户立即看到该页面。但是通过这种方法,您可以让客户端应用程序负责设置可能不需要的员工相关数据。