【问题标题】:Re-Open WPF Window from a Console application从控制台应用程序重新打开 WPF 窗口
【发布时间】:2011-12-24 06:13:39
【问题描述】:

我想从控制台应用程序打开 WPF 窗口。参考this post后,效果很好。

问题是:当用户(手动)关闭 WPF 窗口时,无法再从控制台重新打开,抛出异常消息:“Cannot create more than one System.Windows.Application instance in the same应用程序域。”

代码如下:

class Program
    {
        static void Main(string[] args)
        {
            string input=null;
            while ((input = Console.ReadLine()) == "y")
            {
                //Works fine at the first iteration,
                //But failed at the second iteration.
                StartWpfThread();
            }
        }
        private static void OpenWindow()
        {
            //Exception(Cannot create more than one System.Windows.Application instance in the same AppDomain.)
            //is thrown at the second iteration.
            var app = new System.Windows.Application();
            var window = new System.Windows.Window();
            app.Run(window);
            //User  closes the opened window manually.
        }
        private static void StartWpfThread()
        {
            var thread = new Thread(() =>
            {
                OpenWindow();
            });
            thread.SetApartmentState(ApartmentState.STA);
            thread.IsBackground = false;
            thread.Start();
        }
    }

如何重新打开 WPF 窗口?

【问题讨论】:

    标签: c# .net wpf winforms console-application


    【解决方案1】:

    应用程序不能和窗口一起创建,只能单独创建一次,同时通过分别设置ShutdownMode确保窗口关闭后不退出,例如

    class Program
    {
        static Application app;
        static void Main(string[] args)
        {
            var appthread = new Thread(new ThreadStart(() =>
                {
                    app = new Application();
                    app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
                    app.Run();
                }));
            appthread.SetApartmentState(ApartmentState.STA);
            appthread.Start();
    
            while (true)
            {
                var key =Console.ReadKey().Key;
                // Press 1 to create a window
                if (key == ConsoleKey.D1)
                {
                    // Use of dispatcher necessary as this is a cross-thread operation
                    DispatchToApp(() => new Window().Show());
                }
                // Press 2 to exit
                if (key == ConsoleKey.D2)
                {
                    DispatchToApp(() => app.Shutdown());
                    break;
                }
            }
        }
    
        static void DispatchToApp(Action action)
        {
            app.Dispatcher.Invoke(action);
        }
    }
    

    此外,如果您想重新打开同一个窗口,请确保它永远不会完全关闭,为此您可以处理Closing 事件并使用e.Cancel = true; 取消它,然后只需调用Hide窗口“关闭”它,Show 稍后再次“打开”它。

    【讨论】:

    • 不在另一个线程中运行应用程序并且从不调用 app.Run() 是否有任何负面影响?即只创建一个新的应用程序对象,然后创建一个新的窗口对象,然后调用 myWindow.ShowDialog()。据我所知,调度程序会自动创建并附加到当前线程,而 Application.Current 仍用于管理资源。
    • @Matt:这不是你通常会做的事情,所以我不知道,因为我从来没有这样做过。您也可以拥有没有任何应用程序的窗口...
    【解决方案2】:

    当您将 window 作为参数添加到 app.Run 时,您会将应用的生命周期链接到您的窗口。不要那样做:

    private static void OpenWindow()
            {
                //Exception(Cannot create more than one System.Windows.Application instance in the same AppDomain.)
                //is thrown at the second iteration.
                var app = new System.Windows.Application();
                var window = new System.Windows.Window();
                app.Run();
                window.Show();
                //User  closes the opened window manually.
            }
    

    【讨论】:

    • 谢谢!但是在我将 Window.Show() 与 app.Run() 方法分开后,窗口就永远不会显示了。
    • 除了表单之外,您还可以传递一个 ApplicationContext 来运行。我不知道它是如何工作的,但也许在该课程中可以解决您的问题。
    【解决方案3】:

    我自己没有机会对此进行测试,但是在阅读了您的错误之后,我发现了一些信息。基本上,听起来你正在运行的AppDomain 每个应用程序只能使用一次 - 所以也许你每次想要重新创建应用程序时都需要创建一个新的AppDomain。有关这方面的更多信息,请参阅here。

    或者,您可以使用System.Diagnostics.Process.Start(...) 来正确启动应用程序。有关 Process 类的文档,请参阅 here。

    最后,如果您只是想让用户从命令行运行应用程序,编写命令脚本并从命令行执行它可能会更简单。

    【讨论】:

    • 谢谢!不幸的是,在我的应用程序中,WPF 窗口将共享来自控制台应用程序的许多变量,因此它们必须在同一个进程中运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-20
    • 2022-01-14
    • 2017-09-09
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多