2012-08-10 28 views
2

在ASP.NET中使用Autofac和ContainerDisposalModule一樣,我如何支持需要解決組件依賴關係的fire和forget調用?我遇到的問題是ASP.NET請求在任務運行之前完成並部署了請求的生命週期範圍,因此需要在新線程中解析的任何組件都會失敗,並顯示「實例無法解析並且從此LifetimeScope中不能創建嵌套壽命,因爲它已經被處置「。在ASP.NET中使用Autofac支持火和忘記呼叫的最佳方式是什麼?我不想延遲執行某些可以在後臺線程上完成的任務的請求。在後臺解析Autofac組件在ASP.NET中的任務

回答

2

您需要創建一個獨立於請求生存期範圍的新生命週期範圍。下面的博客文章展示了一個如何使用MVC來實現這個功能的例子,但是可以將相同的概念應用於WebForms。

http://aboutcode.net/2010/11/01/start-background-tasks-from-mvc-actions-using-autofac.html

如果您需要確保異步工作請求完成後,那麼這是不是一個好方法絕對執行。在這種情況下,我會建議在請求期間將消息發佈到隊列中,以允許單獨的進程提取並執行工作。

2

答案張貼由Alex適應當前Autofac和MVC版本:

  • 使用InstancePerRequest的數據庫上下文
  • 添加ILifetimeScope的依賴才能到容器
  • SingleInstance確保它的根壽命範圍
  • 使用HostingEnvironment.QueueBackgroundWorkItem可靠在後臺運行東西
  • 使用MatchingScopeLifetimeTags.RequestLifetimeScopeTag以避免必須知道的標記名autofac用來PerRequest使用壽命期

https://groups.google.com/forum/#!topic/autofac/gJYDDls981A https://groups.google.com/forum/#!topic/autofac/yGQWjVbPYGM

要點:https://gist.github.com/janv8000/35e6250c8efc00288d21

的Global.asax.cs:

protected void Application_Start() { 
    //Other registrations 
    builder.RegisterType<ListingService>(); 
    builder.RegisterType<WebsiteContext>().As<IWebsiteContext>().InstancePerRequest(); //WebsiteContext is a EF DbContext 
    builder.RegisterType<AsyncRunner>().As<IAsyncRunner>().SingleInstance(); 
} 

AsyncRunner .cs

public interface IAsyncRunner 
{ 
    void Run<T>(Action<T> action); 
} 

public class AsyncRunner : IAsyncRunner 
{ 
    public ILifetimeScope LifetimeScope { get; set; } 

    public AsyncRunner(ILifetimeScope lifetimeScope) 
    { 
     Guard.NotNull(() => lifetimeScope, lifetimeScope); 
     LifetimeScope = lifetimeScope; 
    } 

    public void Run<T>(Action<T> action) 
    { 
     HostingEnvironment.QueueBackgroundWorkItem(ct => 
     { 
      // Create a nested container which will use the same dependency 
      // registrations as set for HTTP request scopes. 
      using (var container = LifetimeScope.BeginLifetimeScope(MatchingScopeLifetimeTags.RequestLifetimeScopeTag)) 
      { 
       var service = container.Resolve<T>(); 
       action(service); 
      } 
     }); 
    } 
} 

控制器

public Controller(IAsyncRunner asyncRunner) 
{ 
    Guard.NotNull(() => asyncRunner, asyncRunner); 
    AsyncRunner = asyncRunner; 
} 

public ActionResult Index() 
{ 
    //Snip 
    AsyncRunner.Run<ListingService>(listingService => listingService.RenderListing(listingGenerationArguments, Thread.CurrentThread.CurrentCulture)); 
    //Snip 
} 

ListingService

public class ListingService : IListingService 
{ 
    public ListingService(IWebsiteContext context) 
    { 
    Guard.NotNull(() => context, context); 
    Context = context; 
    } 
}