импортировать много деталей из различных сборок в моем классе, как это:Использование «System.Lazy.LazyThreadSafetyMode» с MEF
[ImportMany(typeof(IServiceProvider))]
private IEnumerable<Lazy<IServiceProvider, IDictionary<string, object>>> ServiceProviders
{
get;
set;
}
После импортирован части, поставщики услуг создаются по запросу:
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;
}
Как я уже отмечал выше, многие потоки пытаются получить value
переменной lazy
(создайте новый экземпляр, если он еще не создан) в одно и то же время.
Lazy<T>
имеет конструктор, который позволяет создать экземпляр (value
) в thread-safe
образом, как это:
// 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
, принимали заботы создания объекта при импорте деталей, и я хочу использовать Lazy
конструктор, который позволяет для потокобезопасного создания value
, но я не знаю как.
На самом деле мне нужно обновить 'DirectoryCatalog', чтобы добавить/удалить и заменить измененный плагины из контейнера. Это против безопасности потоков? – Xaqron
@ Xaqron Да, это было бы против безопасности потоков. Если это серверное приложение, вероятно, лучше всего создать новый каталог и контейнер, которые будут использоваться для всех будущих запросов, и пусть текущий контейнер будет использоваться для завершения текущих запросов. Если это клиентское приложение, вам, вероятно, потребуется приостановить работу над любыми другими потоками, которые могут обращаться к контейнеру, прежде чем обновлять каталог. –