2011-08-29 15 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秒間、他の(似たような)クラスを並行して作成することができなくなりました。私が単にスレッドプールにタスクを置くと、最終的に私のプロダクトキャッシュを必要とする別のクラスが初期化コードを実行していて、まだ完全には初期化されていないデータ構造にアクセスすることになります(この場合、キャッシュミスにとDBの呼び出し特定の製品をフェッチすると、30秒で多くのそのような要望がある場合があります)

おかげ オスカー

+0

初期化するクラスの構造はいくつかありますか? – onof

+0

小さな例を追加 – Oskar

答えて

1

あなたは、実行中のタスクのリストを作成し実行する必要がありますそれらを並列に実行し、Task.WaitAll()を使用してタスクが完了するのを待ってから続行します。

は、.NET 4には、この作業をする必要があり、およびエラー処理が容易になる。

古い学校.NETで
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!"); 
    } 
} 

、これを試してみてください。初期化可能なオブジェクトごとにインターフェイスを使用していると仮定していますが、エラー処理を省略しました。

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

私はあなたが意味するものを見ています。モジュールの初期化中に上記のコードを使用して、依存関係注入を処理する必要のある型のインスタンスを並列に登録することができます。しかし、さまざまなタイプ間の依存関係に問題が生じる可能性があります。 –

関連する問題