2017-02-19 1 views
1

Ich arbeite mit einer WPF-basierten Anwendung und Autofac verwenden, um die Abhängigkeit von DbContext von Entityframework aufzulösen. Ich habe den folgenden Code verwendet, um mein Datenmodul zu registrieren.Multithreading-Problem mit Autofac in WPF-Anwendung

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(); 
    } 
} 

Dies funktioniert im Normalszenario, aber bei der Verwendung von TPL aufgrund gleichzeitiger Anrufe zu Repository, erstellt es Fehler, der besagte, dass „ExecuteReader erfordert eine offene und verfügbare Verbindung. Der aktuelle Status des Anschlusses offen ist.“

In der Webanwendung kann dies mithilfe von InstancePerRequest aufgelöst werden, um die Abhängigkeit pro Anforderung zu lösen. In WPF muss diese Abhängigkeit jedoch pro Threadanforderung aufgelöst werden. Gibt es einen Ausweg dafür?

Ich habe InstancePerRequest Zusammenfassung oder Autofac bewertet und es heißt, dass diese Methode für Web-Anforderung nur verwendet wird:

// 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.). 

Update:

Dies ist eine einfache Asynchron-Methode, die ich verwenden, um zu bekommen die Daten:

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

Hier ist OnLoadClientDetail gebunden an Auswahl ändern Ereignis einer Combobox. Wenn Benutzer die Auswahl häufig ändern, wird diese Methode mehrmals aufgerufen. Der _collectionService wird in das Viewmodel eingefügt und verfügt über InstancePerLifetimeScope define. Also, wie kann ich verschiedene Möglichkeiten für all diese Anrufe bekommen?

+0

Warum brauchen Sie Instanz pro Thread haben? – MaKCbIMKo

+0

@MaKCbIMKo Tatsächlich gibt es mehrere Threads, die auf die gleiche SQL-Tabelle zugreifen, aufgrund derer die Tabelle gesperrt ist, und ich bekam die Ausnahme "ExecuteReader benötigt eine offene und verfügbare Verbindung. Der aktuelle Status der Verbindung ist offen." –

+0

Genau hier ist das 'InstancePerLifetimeScope' gemeint. Sie umbrechen eine logische Arbeitseinheit innerhalb eines Gültigkeitsbereichs für die Gültigkeitsdauer und führen eine Auflösung aus diesem Bereich durch. Dies stellt sicher, dass jede Arbeitseinheit ihren eigenen 'DataContext' hat und dies die gemeinsame Nutzung von Instanzen über Threads oder Operationen hinweg verhindert. – Steven

Antwort

0

Soweit ich sehen kann, teilen Sie die _collectionService Instanz über die verschiedenen Event-Handler, indem Sie es durch Constructor Injection injizieren.

Es ist besser, wahrscheinlich Method Injection hier zu verwenden, so dass Sie die Instanz pro Anruf erhalten, wie Sie benötigen, ist es vor dem Verfahren zu lösen:

builder.Register(c => 
{ 
    var result = new MyObjectType(); 
    var dep = c.Resolve<TheDependency>(); 
    result.SetTheDependency(dep); 
    return result; 
});