Dispatcher.CurrentDispatcher возвращает ноль - PullRequest
0 голосов
/ 17 мая 2018

Я пытаюсь закрыть окно WPF, которое я создал в отдельном потоке от основного потока размещения (основной поток - это приложение PDM, которое я не могу контролировать).Хост-приложение ссылается на мою сборку (это плагин). Я не знаю, но почему Диспетчер всегда нулевой .Создание WaitView на главном приложении для меня не вариант.

Спасибо, ребята!

    var WaitViewModel = new MVVM.ViewModels.WaitViewModel();
                        MVVM.Views.WaitView WaitView = default(MVVM.Views.WaitView);
                        Dispatcher dispatcher = default(Dispatcher); 
                        var thread = new Thread(new ThreadStart(() =>
                        {
                            dispatcher = Dispatcher.CurrentDispatcher; 
                            WaitView = new MVVM.Views.WaitView();
                            WaitView.Topmost = true;
                            WaitView.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                            WaitView.DataContext = WaitViewModel;
                            WaitView.Show();
                            System.Windows.Threading.Dispatcher.Run();
                        }));
                        thread.SetApartmentState(ApartmentState.STA);
                        thread.IsBackground = true;
                        thread.Start();


'unrelated code here
if (dispatcher != null)
dispatcher.Invoke(()=>
{
WaitView.Close();
});

Ответы [ 3 ]

0 голосов
/ 17 мая 2018

Вы должны захватить диспетчер до создания потока, а затем передать его в поток.

В духе не делайте этого , вы не должны создавать какие-либо формыЭлементы пользовательского интерфейса в других потоках, даже если они помечены как STA.Порождение дочерних потоков, которые просто запускаются в вечность, не так хорошо, как потенциально несколько насосов сообщений.Итак, ваш базовый дизайн немного ошибочен.

Исправьте это, и ваши другие проблемы исчезнут.

Надеюсь, вы не делаете все это, скажем, из консольного приложения, которое пытается сделать так, чтобы ваши окна были частью другого процесса?

0 голосов
/ 17 мая 2018

Решение - обработать закрытие вида из кода вида позади.

Я добавил свойство CloseRequest в ViewModel.

Код вида сзади:

  WaitViewModel WaitViewModel;
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // get data context 
             WaitViewModel = this.DataContext as WaitViewModel;
            WaitViewModel.PropertyChanged += WaitViewModel_PropertyChanged;
        }

        private void WaitViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if(e.PropertyName == "CloseRequest")
            {
                Dispatcher dispatcher = this.Dispatcher;
                if (WaitViewModel.CloseRequest)
                    dispatcher.Invoke(() => { 
                    this.Close();
                    });
            }
        }
0 голосов
/ 17 мая 2018

Два способа сделать это:

  1. Передать диспетчер представления в модель представления через конструктор.

    public MyClass
    {
        public MyClass(Dispatcher dispatcher)
        {
             // use your view's dispatcher.
        }
    {
    
  2. ИспользоватьДиспетчер приложения по умолчанию.

    Dispatcher dispatcher = App.Current.Dispatcher;
    

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

...