2011-08-29 74 views
1

如何设置Unity,以便类可以异步初始化而不阻止其他模块的加载(仅阻止显式需要异步类型实例的其他类型)?我正在考虑的类是参考数据缓存,它从数据库中提取常用数据的快照,并且我需要在让其他模块访问它之前完成预先缓存(如果请求在我的类I中被阻止将迅速阻止主线程并阻止所有其他模块进行初始化)。这已成为我有多个这样的引用数据类如何为类型/模块的异步初始化配置Unity

举例来说更为重要,说我有一个这样的类:

public class ProductCache{ 

    public ProductCache(){} 

    public Initialize(){ 
     // a very slow DB call to fetch frequently used products 
     Thread.Sleep(30*1000); 
    } 

    public Product FindProduct(string productDescription){ 
     /* check cache, if not there try the db */ 
    } 
} 

如果我调用初始化从构造我会阻塞调用它的线程(来自Unity)30秒钟,阻止我同时创建其他(类似)类。如果我简单地将任务放在线程池上,Unity最终会达到需要我的产品缓存的另一个类正在执行其初始化代码的地步,然后访问尚未完全初始化的数据结构(在这种情况下,会导致在高速缓存未命中和数据库的调用来获取特定的产品,并有可能在30秒内很多这样的请求)

感谢 奥斯卡

+0

你能提供一些代码,那就是你正在初始化的类的结构吗? – onof

+0

增加了一个小例子 – Oskar

回答

1

你需要做的正在运行的任务列表,请执行它们并行,并使用Task.WaitAll()等待它们完成后再继续。

在.NET 4中,这应该工作和错误处理变得容易:

public void InitializeAll() 
{ 
    List<Task> initTasks = new List<Task>(); 

    ProductCache productCache = new ProductCache(); 
    SomeOtherCache someOtherCache = new SomeOtherCache(); 

    initTasks.Add(Task.Factory.StartNew(() => productCache.Initialize())); 
    initTasks.Add(Task.Factory.StartNew(() => someOtherCache.Initialize())); 

    try 
    { 
     Task.WaitAll(initTasks.ToArray()); 
    } 
    catch (AggregateException ex) 
    { 
     Console.WriteLine("Oh dear!"); 
    } 
} 

在老派的.Net,试试这个。我假设你为每个可初始化的对象使用一个接口,并且我省去了错误处理:

public void InitializeAll(IEnumerable<IInitializable> initializeUs) 
{ 
    List<WaitHandle> handles = new List<WaitHandle>(); 

    foreach(IInitializable init in initializeUs) 
    { 
     // Make a copy of the reference in the local scope 
     IInitializable temp = init; 

     ManualResetEvent done = new ManualResetEvent(false); 
     handles.Add(done); 

     ThreadPool.QueueUserWorkItem(delegate 
     { 
      try 
      { 
       temp.Initialize(); 
      } 
      finally 
      { 
       done.Set(); 
      } 
     }); 
    } 

    // Wait for all the handles to be set 
    WaitHandle.WaitAll(handles.ToArray()); 
} 
+0

是的,这解决了这个问题。我想我希望Unity中的某些东西(比如说一个标记组件的属性)会触发这种行为。它也能够使用模块依赖性来确保正确解释任何依赖关系 – Oskar

+0

我明白你的意思了。您可以在模块初始化期间使用上面的代码来并行注册类型的实例,这应该处理依赖注入。不过,您可能会遇到不同类型之间依赖关系的问题。 –