I want to open Window B from Window A, inside a Button click event, as follows:
我想在Window Click事件中从Window A打开Window B,如下所示:
MainWindow mainWin = new MainWindow();
mainWin.Show();
The problem is that in MainWindow constructor there's the InitializeComponent method and some others, and it takes a couple of seconds to execute, blocking the UI (I have a spinning icon and it doesn't spin).
问题是在MainWindow构造函数中有InitializeComponent方法和其他一些方法,并且需要几秒钟的时间来执行,阻塞UI(我有一个旋转的图标,它不会旋转)。
Here's what I've tried:
这是我尝试过的:
await Task.Run(() => mainWin = new MainWindow()); // Exception: thread must be STA :(
and
await Dispatcher.InvokeAsync(new Action(() => mainWin = new MainWindow()));
and
await Dispatcher.BeginInvoke(new Action(async delegate {
mainWin = new MainWindow();
}));
EDIT: This is how MainWindow constructor looks like:
编辑:这是MainWindow构造函数的样子:
public MainWindow()
{
InitializeComponent(); // Takes about 3 seconds...
}
By no means I'm a C# or WPF or threading expert, I found those "solutions" and I just tried them with no success. I want to know if there's a way to execute InitializeComponent async or how to keep my animation playing.
绝不是我是C#或WPF或线程专家,我找到了那些“解决方案”而我只是尝试了它们并没有成功。我想知道是否有办法执行InitializeComponent异步或如何保持我的动画播放。
I'm using C# WPF (no MVVM) and .NET Framework 4.6. Thank you in advance.
我正在使用C#WPF(没有MVVM)和.NET Framework 4.6。先谢谢你。
1 个解决方案
#1
-1
You can create window in another thread. The downside is that any access to that window's controls from main thread must be done via Dispatcher.Invoke/BeginInvoke.
您可以在另一个线程中创建窗口。缺点是必须通过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"; });
}
}
#1
-1
You can create window in another thread. The downside is that any access to that window's controls from main thread must be done via Dispatcher.Invoke/BeginInvoke.
您可以在另一个线程中创建窗口。缺点是必须通过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"; });
}
}