在ViewModel上从后台线程打开新窗口

时间:2011-11-18 08:53:25

标签: wpf multithreading mvvm

所以我有一个带有启动画面的WPF应用程序(MVVM)。在启动画面启动时,我在ViewModel上有一个后台线程,它执行一些启动相关的活动。在某些情况下,我想打开几个额外的窗口(需要用户输入等...)。我在尝试这样做时遇到了许多问题/错误/异常(主要是围绕新窗口 - 也是MVVM - 尝试填充其UI项目,例如组合框)。所以我把问题拉回到一个更简单的形式 - “tempWindow”没有任何东西,所以它不会抛出UI填充错误,但基本上它只是打开它们,一旦后台线程完成,关闭所有。如果有人能指出我正确的方向,我在这里做错了,我们将不胜感激。

ViewModel的构造函数启动后台线程

public SplashScreenViewModel()
{            
   this.LoadingStatusText = "Starting Startup Processing ... ";
   this.VersionNumber = "version " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();

   var threadBackgroundStartUpProcesses = new Thread(new ThreadStart(this.BackgroundStartUpProcesses));
   threadBackgroundStartUpProcesses.SetApartmentState(ApartmentState.STA);
   threadBackgroundStartUpProcesses.IsBackground = true;
   threadBackgroundStartUpProcesses.Start();
}

后台线程应该只打开三个窗口(它会这样做)但是这些窗口应该保持打开状态(一旦线程完成它们就会消失)。

private void BackgroundStartUpProcesses()
{
    for (int i = 0; i < 3; i++)
    {
        var objTempWindow = new tempWindow();
        objTempWindow.Show();
    }
}

//编辑:使用响应更新,现在当TempWindow有一个从TempWindowViewModel填充的comboBox时出现错误。

private void BackgroundStartUpProcesses()
{
    for (int i = 0; i < 3; i++)
    {
        var objTempWindow = new tempWindow();
        objTempWindow.Show();
    }

    System.Windows.Threading.Dispatcher.Run();
}

当它打开TempWindow异常时:“调用线程无法访问此对象,因为另一个线程拥有它。”抛出并且似乎是在尝试填充该窗口上的ComboBox时。

2 个答案:

答案 0 :(得分:3)

我怀疑窗户需要一个拥有者,当所有者死亡时,窗户也是如此。打开主线上的窗口会使它们粘在一起。像这样......

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        var threadBackgroundStartUpProcesses = new Thread(new ParameterizedThreadStart(this.BackgroundStartUpProcesses));
        threadBackgroundStartUpProcesses.SetApartmentState(ApartmentState.STA);
        threadBackgroundStartUpProcesses.IsBackground = true;
        threadBackgroundStartUpProcesses.Start(System.Windows.Threading.Dispatcher.CurrentDispatcher);
    }

    private void BackgroundStartUpProcesses(object d)
    {
        System.Windows.Threading.Dispatcher dispatcher = (System.Windows.Threading.Dispatcher) d;
         for (int i = 0; i < 3; i++)
         {
             dispatcher.BeginInvoke((Action)(() =>
             {
                 var objTempWindow = new tempWindow();
                 objTempWindow.Show();

             }));

         }

    }
}

修改

我刚刚对WPF线程进行了一些挖掘,看起来你可以在多个线程上打开窗口,但是你需要启动新的调度程序。请参阅本页末尾附近:

http://msdn.microsoft.com/en-us/library/ms741870.aspx

BackgroundStartupProcesses的{​​{1}}下添加此行

objTempWindow.Show()

答案 1 :(得分:0)

您是否在关闭启动画面之前设置了MainWindow? WPF将应用程序的第一个打开窗口设置为MainWindow,除非您已更改ShutdownMode的{​​{1}},否则关闭启动屏幕后应用程序将关闭。< / p>