Dispatcher.CurrentDispatcher返回null

时间:2018-05-16 23:53:16

标签: c# multithreading dispatcher

我正在尝试关闭我在主托管线程的单独线程中创建的WPF窗口(主线程是我无法控制的PDM应用程序)。主机应用程序引用我的程序集(它是一个插件)。 我不知道为什么Dispatcher始终为null 。在主机应用程序上创建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 :(得分:0)

两种方法:

  1. 通过构造函数将视图的调度程序传递到视图模型中。

    public MyClass
    {
        public MyClass(Dispatcher dispatcher)
        {
             // use your view's dispatcher.
        }
    {
    
  2. 使用应用程序默认调度程序。

    Dispatcher dispatcher = App.Current.Dispatcher;
    
  3. 为清楚起见,真正的视图模型不会使用调度程序,因为它位于UI线程上。不过,您可以使用常规方法并让视图调度程序在View上执行它们。

答案 1 :(得分:-1)

您应该在创建线程之前抓住调度程序,然后将其传递给线程。

本着不要那样做的精神,你不应该在其他线程中创建任何形式的UI元素,即使它们被标记为STA。产生刚刚运行到永恒的子线程并不是那么好,因此可能是多个消息泵。所以,你的基础设计有点瑕疵。

解决这个问题,你的其他问题就消失了。

我希望你没有做这一切,说一个控制台应用程序试图让它看起来好像你的窗口是不同进程的一部分?

答案 2 :(得分:-1)

解决方案是处理从后面的视图代码中关闭视图。

我已经向ViewModel添加了一个名为CloseRequest的属性。

查看后面的代码:

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