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.
Eigentlich brauche ich die 'DirectoryCatalog' aufzufrischen hinzufügen/entfernen und geänderte Plugins aus dem Behälter zu ersetzen. Ist das gegen Fadensicherheit? – Xaqron
@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. –