SynchronizationContext.Current не имеет значения при разрешении с Unity в WPF - PullRequest
5 голосов
/ 21 февраля 2012

У меня есть код WPF, который выглядит примерно так.

public class AlphaProductesVM : BaseModel
{
    private  ObservableCollection<Alphabetical_list_of_product> _NwCustomers;
    private int i = 0;

    public AlphaProductesVM ()
    {
        _NwCustomers = new ObservableCollection<Alphabetical_list_of_product>();
        var repository = new NorthwindRepository();
           repository
               .GetAllProducts()
               .ObserveOn(SynchronizationContext.Current)
               .Subscribe(AddElement);
    }
    public void AddElements(IEnumerable<Alphabetical_list_of_product> elements)
    {
        foreach (var alphabeticalListOfProduct in elements)
        {
            AddElement(alphabeticalListOfProduct);
        }
    }


    public ObservableCollection<Alphabetical_list_of_product> NwCustomers
    {
        get { return _NwCustomers; }
        set { _NwCustomers = value; }
    }}

Я использую Unity для разрешения вышеупомянутого AlphaProductesVM. Это происходит мгновенно, когда модуль обнаруживается с помощью PRISM и UnityBootstrapper. Во время выполнения .ObserveOn(SynchronizationContext.Current) выдает исключение, а SynchronizationContext.Current содержит значение null.

Ответы [ 3 ]

4 голосов
/ 21 февраля 2012

Свойство SynchronizationContext.Current будет возвращать значение только при вызове из основного потока .

Если вам нужно использовать SynchronizationContext объект в потоках , отличный от основного потока , вы можете передать экземпляр SynchronizationContext , связанный с основным потоком, в классы, которые нуждаются в этом в качестве зависимости .

Если вы выберете это решение, вы можете зарегистрировать объект SynchronizationContext , полученный из свойства SynchronizationContext.Current , в главном потоке как singleton в вашем контейнере. Таким образом, все запросы на SynchronizationContext с этого момента будут автоматически удовлетворяться контейнером с синглтоном:

// Must run in the main thread
container.RegisterInstance(SynchronizationContext.Current);
0 голосов
/ 21 февраля 2012

Я не уверен, будет ли это популярным предложением, но вы можете лениво создавать и подписываться на свою коллекцию.Тогда при первом доступе к NwCustomers из потока пользовательского интерфейса все будет правильно запущено.

public AlphaProductesVM (){}

public ObservableCollection<Alphabetical_list_of_product> NwCustomers
{
    get { 
          if(_NwCustomers == null)
          {
              _NwCustomers = new ObservableCollection<Alphabetical_list_of_product>();
              var repository = new NorthwindRepository();
                  repository
                  .GetAllProducts()
                  .ObserveOn(SynchronizationContext.Current)
                  .Subscribe(AddElement);
          }
          return _NwCustomers; 
    }
}

или, если вы внедрили диспетчер потока пользовательского интерфейса в модель представления, вы можете подписаться на это в конструкторе.

              var repository = new NorthwindRepository();
                  repository
                  .GetAllProducts()
                  .ObserveOn(theUIdispatcher)
                  .Subscribe(AddElement);
0 голосов
/ 21 февраля 2012

Хотя существует реализация SynchronizationContext для WPF, она не рекомендуется для использования. WPF имеет приложения, отвечающие на сборку от Dispatcher до .

Кроме того, SynchronizationContext.Current имеет значение, только если вы находитесь в потоке пользовательского интерфейса. Если ваша логика работает в фоновом потоке, Current всегда будет нулевым.

...