如何在不阻止WPF中的UI线程的情况下执行InitializeComponent?

时间:2018-08-16 00:00:45

标签: c# wpf windows

我要在Button单击事件中从窗口A打开窗口B,如下所示:

MainWindow mainWin = new MainWindow();
mainWin.Show();

问题在于MainWindow构造函数中有InitializeComponent方法和其他一些方法,它需要几秒钟的时间执行,从而阻塞了UI(我有一个旋转的图标,它不会旋转)。

这是我尝试过的:

await Task.Run(() => mainWin = new MainWindow()); // Exception: thread must be STA :(

await Dispatcher.InvokeAsync(new Action(() => mainWin = new MainWindow()));

await Dispatcher.BeginInvoke(new Action(async delegate {
    mainWin = new MainWindow();
}));

编辑:这是MainWindow构造函数的外观:

public MainWindow()
{
    InitializeComponent(); // Takes about 3 seconds...
}

绝不是我是C#或WPF或线程专家,我找到了这些“解决方案”,而我只是尝试了但没有成功。我想知道是否有一种方法可以异步执行InitializeComponent或如何保持动画播放。

我正在使用C#WPF(无MVVM)和.NET Framework 4.6。预先谢谢你。

1 个答案:

答案 0 :(得分:-1)

您可以在另一个线程中创建窗口。缺点是必须通过Dispatcher.Invoke / BeginInvoke从主线程访问该窗口的控件。

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.IO;
using System.Threading;
using System.Windows.Threading;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {             

        public MainWindow()
        {
            InitializeComponent();            
        }

        void ThreadProc()
        {
            //create second window in background thread
            Window window2 = new Window2();
            window2.Show();

            //start WPF message loop
            DispatcherFrame frame = new DispatcherFrame();            
            Dispatcher.PushFrame(frame);
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            //start background thread
            Thread thread2;
            thread2 = new Thread(ThreadProc);
            thread2.IsBackground = true;
            thread2.SetApartmentState(ApartmentState.STA);
            thread2.Start();
        }  

    // To access Window2 from MainWindow, do like that:
    //window2.Dispatcher.Invoke(() => { window2.Title = "Hello, world"; });    

    }    
}