2017-02-19 43 views
1

Я работаю с приложением на основе WPF и использую Autofac для разрешения зависимости DbContext от Entityframework. Я использовал приведенный ниже код для регистрации моего модуля данных.Проблема многопоточности с Autofac в приложении WPF

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 требует открытого и доступного подключения. Текущее состояние соединения с использованием открыто.»

В веб-приложении это может быть разрешено с помощью экземпляра InstancePerRequest для разрешения зависимости для каждого запроса, но в WPF мне нужно разрешить эту зависимость для запроса на поток. Есть ли выход для этого?

У меня есть обзор резюме InstancePerRequest или autofac и заявляет, что этот метод используется для веб-запроса только:

// 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:

Это простой метод асинхронной, который я использовал, чтобы получить данные:

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