2017-02-19 2 views
1

私は、WPFベースのアプリケーションを使用し、Autofacを使用してEntityframeworkのDbContextの依存関係を解決しています。私は私のデータモジュールを登録するために以下のコードを使用しました。WPFアプリケーションでのAutofacでのマルチスレッドの問題

public class DataModule : Module 
{ 
    protected override void Load(ContainerBuilder builder) 
    { 
     builder.RegisterType<DataContext>() 
      .As<IDbContext>() 
      .WithParameter("nameOrConnectionString", "DefaultConnectionString") 
      .InstancePerLifetimeScope(); 

     builder.RegisterGeneric(typeof(Repository<>)) 
      .As(typeof(IRepository<>)) 
      .InstancePerLifetimeScope(); 
    } 
} 

通常のシナリオで使用しながら、これは正常に動作しますが、原因リポジトリへの同時コールに、TPLを使用している間、それはというエラーを作成する「のExecuteReaderがオープンし、利用可能な接続が必要です。接続の現在の状態がオープンしています。」

Webアプリケーションでは、これは要求ごとの依存関係を解決するためにInstancePerRequestを使用して解決できますが、WPFではこの依存関係をスレッド要求ごとに解決する必要があります。これにはどのような方法がありますか?

私はInstancePerRequestサマリまたはautofacを確認しており、それは、この方法が唯一のWeb要求のために使用されていると述べている:

// Summary: 
//  Share one instance of the component within the context of a single web/HTTP/API 
//  request. Only available for integration that supports per-request dependencies 
//  (e.g., MVC, Web API, web forms, etc.). 

更新:

これは私が取得するために使用される単純な非同期メソッドでありますデータ:

private async void OnLoadClientDetail() 
    { 
     long clientId = SelectedClient != null ? SelectedClient.Id : 0; 
     var listOfCollection = await _collectionService.GetCollectedCollectionAsync(clientId); 
     CollectionList = new ObservableCollection<CollectedCollection>(listOfCollection); 
    } 

ここで、OnLoadClientDetailは、コンボボックスの選択変更イベントにバインドされています。ユーザーが選択を頻繁に変更すると、このメソッドは複数回呼び出されます。 _collectionServiceはviewmodelに挿入され、InstancePerLifetimeScope定義を持ちます。だから私はどのようにこの呼び出しのための異なる範囲を得ることができますか?

+0

をなぜあなたは、スレッドごとにインスタンスを持っている必要がありますか? – MaKCbIMKo

+0

@MaKCbIMKo実際には、テーブルがロックされているため、同じSQLテーブルにアクセスする複数のスレッドがあり、「ExecuteReaderには開いて使用可能な接続が必要です」という接続があります。 –

+0

これは、 'InstancePerLifetimeScope'が意味するところです。生涯の範囲内で論理的な作業単位をラップし、その範囲から解決します。これにより、すべての作業ユニットが独自の 'DataContext'を持つことが保証され、これによりスレッドまたは操作間でインスタンスの共有が防止されます。 – Steven

答えて

0

私が見る限り、異なるイベントハンドラ間で_collectionServiceインスタンスを共有するには、Constructor Injectionで注入します。

それはおそらくより良いここMethod Injection使用するので、あなたが必要があるとして、あなたは、メソッドの前にそれを解決し、呼び出しごとにインスタンスを取得します:

builder.Register(c => 
{ 
    var result = new MyObjectType(); 
    var dep = c.Resolve<TheDependency>(); 
    result.SetTheDependency(dep); 
    return result; 
}); 
関連する問題