2010-12-29 15 views
2

ich viele Teile aus verschiedenen Baugruppen in meine Klasse wie folgt verwenden importieren:‚System.Lazy.LazyThreadSafetyMode‘ mit MEF

private IServiceProvider GetServiceProvider(String name) 
{ 
    foreach (var serviceProvider in ServiceProviders) 
    { 
     String currentName = (String)serviceProvider.Metadata["Name"]; 
     if (currentName == name) 
      return serviceProvider.Value; // Many threads receive here and try to create new instance. 
    } 

    return null; 
} 
:

[ImportMany(typeof(IServiceProvider))] 
private IEnumerable<Lazy<IServiceProvider, IDictionary<string, object>>> ServiceProviders 
    { 
     get; 
     set; 
    } 

Nach Teile importiert, Dienstleister auf Verlangen werden

Wie ich in obigem Code kommentiert, versuchen viele Threads value des lazy Variable (neu erstellen Instanz davon, wenn diese noch nicht erstellt) bekommen zur gleichen Zeit.

Lazy<T> hat einen Konstruktor, die erlauben Instanz (value) in einer thread-safe Weise zu erstellen, wie folgt aus:

// Something here... 
Dictionary<string, object> metadata = new Dictionary<string,object>(); 
metadata.Add("Name", "test"); 
Lazy<IServiceProvider, IDictionary<string, object>> serviceProvider = new Lazy<IServiceProvider, IDictionary<string, object>>(ServiceProviderValueFactory, metadata, System.Threading.LazyThreadSafetyMode.ExecutionAndPublication); 
// Now access to 'serviceProvider.Value' creates an instance (if not created yet) in a thread-safe manner. 

private IServiceProvider ServiceProviderValueFactory() 
{ 
    // Create and return a new instance of 'IServiceProvider'. 
} 

MEF take Sorgen der Objekterstellung, wenn Teile Import und ich möchte den Lazy Konstruktor verwenden, die erlaubt für Thread-Safe value Erstellung, aber ich weiß nicht wie.

Antwort

2

Wenn Ihr CompositionContainer Erstellen isThreadSafe=true an den Konstruktor übergeben.

Beachten Sie, dass es nicht sicher ist, Neuzusammenstellungen in einem threadsicheren Container durchzuführen. Daher sollten Sie keine Kataloge verwenden, die sich ändern, oder CompositionBatch oder die Erweiterungsmethode .

+0

Eigentlich brauche ich die 'DirectoryCatalog' aufzufrischen hinzufügen/entfernen und geänderte Plugins aus dem Behälter zu ersetzen. Ist das gegen Fadensicherheit? – Xaqron

+0

@Xaqron Ja, das wäre gegen Fadensicherheit. Wenn es sich um eine serverseitige Anwendung handelt, ist es wahrscheinlich am besten, nur einen neuen Katalog und Container zu erstellen, der für alle zukünftigen Anfragen verwendet wird, und den aktuellen Container für die aktuellen Anforderungen verwenden zu lassen. Wenn es sich um eine Client-Anwendung handelt, müssen Sie wahrscheinlich die Arbeit an anderen Threads pausieren, die möglicherweise auf den Container zugreifen, bevor Sie die Katalogaktualisierung durchführen. –

1

Ich bin nicht überzeugt, dass dies etwas ist, können Sie ändern. Der Typ wird über die interne Klasse ExportServices initialisiert und kann nicht überschrieben werden. Wenn subclassed Sie ExportProvider das Ziel GetExports oder GetExportsCore die Lazy<T, M> sind nicht abstrakt oder virtuelle Rückkehr so ​​nicht außer Kraft gesetzt werden kann.

In ExportServices wird hart codiert als:

return new Lazy<T, M>(..., LazyThreadSafetyMode.PublicationOnly); 
+0

+1 für Details wusste ich nicht. Obwohl die Quelle auf "Codeplex" verfügbar ist, werde ich meine Version nicht abzweigen. Neue Bibliotheken wie 'MEF' und' Lazy' haben Probleme mit parametrisierten Konstruktoren und haben mich zu einem Problem gemacht. – Xaqron