如何在不同的线程上创建和显示WPF窗口?

Mik*_*erg 36 wpf multithreading

我需要从同一个进程创建两个(或更多)WPF窗口.但窗口必须由单独的线程处理,因为它们不应该相互阻塞.我该怎么做呢?

在WinForms中,这是通过以下方式实现的:

  • 开始一个新的主题
  • 从新线程创建表单
  • 使用表单作为参数调用Application.Run

但是我如何在WPF中做同样的事情呢?

Ken*_* K. 50

正如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();
}
Run Code Online (Sandbox Code Playgroud)

编辑:这是一个古老的答案,但由于它似乎经常访问,我还可以考虑以下修改/改进(未测试).

如果你想关闭这样一个窗口,只需从线程(委托)外部保持对Window对象的引用,然后在它上面调用close,如下所示:

void CloseWindowSafe(Window w)
{
    if (w.Dispatcher.CheckAccess())
        w.Close();
    else
        w.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadStart(w.Close));
}

// ...
CloseWindowSafe(tempWindow);
Run Code Online (Sandbox Code Playgroud)

如果新线程可以终止(强制中止),则与注释中的问题一致:

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
}
Run Code Online (Sandbox Code Playgroud)

免责声明:不要在家里这样做,中止线程(几乎总是)违反最佳做法.线程应该通过任何各种同步技术优雅地处理,或者在这种情况下,只需通过调用window.Close()

  • 大.如何关闭以这种方式创建的窗口? (3认同)

Chr*_*tta 16

无论它有什么价值,因为这个答案是Google提供的第一个结果.我还想从Eugene Prystupa的Weblog中添加以下内容:

"这里有一个陷阱,以我们的简化的解决方案.关闭一个特定的窗口不会终止本窗口的线程调度,因此线程保持运行,并关闭所有窗口后,该进程也不会终止,并且将成为一个克隆进程.[的]简单(并且不正确)解决方案是将我们的线程标记为背景(使用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();
}
Run Code Online (Sandbox Code Playgroud)

  • 如果上面的一个不再有效,类似的参考链接:[在单独的线程中启动WPF窗口,第1部分](http://reedcopsey.com/2011/11/28/launching-a-wpf-window-in-一个-单独线程部分-1 /) (4认同)