我需要从同一个进程创建两个(或更多)WPF窗口。但窗口必须由单独的线程处理,因为它们不应该相互阻塞。我该怎么做?
在WinForms中,这可以通过以下方式实现:
但是我如何在WPF中做同样的事情?
答案 0 :(得分:45)
正如msdn所述:
private void NewWindowHandler(object sender, RoutedEventArgs e)
{
Thread newWindowThread = new Thread(new ThreadStart(ThreadStartingPoint));
newWindowThread.SetApartmentState(ApartmentState.STA);
newWindowThread.IsBackground = true;
newWindowThread.Start();
}
private void ThreadStartingPoint()
{
Window1 tempWindow = new Window1();
tempWindow.Show();
System.Windows.Threading.Dispatcher.Run();
}
编辑: 这是一个古老的答案,但由于它似乎经常被访问,我还可以考虑以下修改/改进(未经测试)。
如果你想要关闭这样一个窗口,只需从线程(委托)外部保留对Window对象的引用,然后调用close,就像这样:
void CloseWindowSafe(Window w)
{
if (w.Dispatcher.CheckAccess())
w.Close();
else
w.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadStart(w.Close));
}
// ...
CloseWindowSafe(tempWindow);
如果新线程可以终止(强制中止),则与评论中的问题一致:
private void ThreadStartingPoint()
{
try{
Window1 tempWindow = new Window1();
tempWindow.Show();
System.Windows.Threading.Dispatcher.Run();
}
catch(ThreadAbortException)
{
tempWindow.Close();
System.Windows.Threading.Dispatcher.InvokeShutdown();
}
//the CLR will "rethrow" thread abort exception automatically
}
免责声明:不要在家中这样做,中止线程(几乎总是)违反最佳做法。应该通过任何各种同步技术优雅地处理线程,或者在这种情况下,只需通过调用window.Close()
答案 1 :(得分:15)
无论价值多少,因为这个答案是Google提供的第一个结果。我还要添加以下Eugene Prystupa's Weblog:
“我们的简化解决方案有一个问题。关闭特定窗口 NOT 终止此窗口的线程调度程序,因此线程继续运行,在关闭所有窗口后,进程将不会终止并且将成为一个ghost进程。[简单]解决这个问题的方法是将我们的线程标记为背景(使用thread.IsBackground = true;)。这将强制它们在主UI线程终止时终止。
正确的实施将在不再需要时正常关闭调度程序。下面的代码是窗口关闭时终止调度程序的策略示例:“
private void OnCreateNewWindow(object sender, RoutedEventArgs e)
{
Thread thread = new Thread(() =>
{
Window1 w = new Window1();
w.Show();
w.Closed += (sender2, e2) =>
w.Dispatcher.InvokeShutdown();
System.Windows.Threading.Dispatcher.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
答案 2 :(得分:3)
我想我找到了答案。看看Jon Skeet在这个question中的答案。
基本上你在你的线程启动方法中这样做:
private void ThreadStartingPoint()
{
Window1 tempWindow = new Window1();
tempWindow.Show();
System.Windows.Threading.Dispatcher.Run();
}
答案 3 :(得分:2)
正是我在寻找的东西。
我这样做是这样的:
App.xaml.cs
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Thread newWindowThread = new Thread(new ThreadStart(ThreadStartingPoint));
newWindowThread.SetApartmentState(ApartmentState.STA);
newWindowThread.IsBackground = true;
newWindowThread.Start();
var window = new MainWindow(newWindowThread);
window.DataContext = new MainWindowViewModel(window);
window.Show();
}
private void ThreadStartingPoint()
{
SplashWindow tempWindow = new SplashWindow();
tempWindow.Show();
System.Windows.Threading.Dispatcher.Run();
}
}
MainWindow.Xaml.cs
public partial class MainWindow : Window
{
public MainWindow(Thread splashWindowThread)
{
InitializeComponent();
MyInializaComponent();
splashWindowThread.Abort();
}
//void DoStuff(){};
}
在程序完成所有加载后,我需要启动闪屏才能消失。