【问题标题】:Application.Current is null, but new Application() still fails?Application.Current 为空,但 new Application() 仍然失败?
【发布时间】:2020-02-14 08:24:54
【问题描述】:

我有一个非托管应用程序,该应用程序将 WPF 程序集用于其某些用户界面。由于这种安排,Application.Current 不会自动创建。所以当第一个 WPF 窗口被加载时,我的代码会这样做:

        if (System.Windows.Application.Current == null)
        {
            new System.Windows.Application();
        }

这是第一次工作,是I've seen recommended的方法。

但是如果用户关闭(唯一的)WPF 窗口,然后再次加载它,即使Current == null 再次在调用 Application ctor 时引发异常。

documentation 中很清楚,每个 AppDomain 只能有一个应用程序 - 但是为什么 Current 为 null 而我却无法创建它?


抛出的异常类型为InvalidOperationException,并有以下消息:

不能在 相同的 AppDomain。

它的InnerException 为空。


为了解决这个问题,我尝试了:

  • 使用ShutdownMode = ShutdownMode.OnLastWindowClose构造Application

  • 当 WPF 窗口关闭时显式调用Current.Shutdown()

但两者都没有任何区别。

还有其他方法可以手动管理Current 对象的生命周期吗?或者我应该尝试在非托管应用程序启动时创建它,然后依赖它在进程的生命周期内始终设置?

【问题讨论】:

  • 什么是异常,以及任何 InnerException?
  • @rfmodulator 好点,我会检查并添加...
  • @rfmodulator 添加
  • 你能创建一个小的工作示例吗?可能有一些变量,例如位数/单元线程等......可能需要考虑。
  • @ΩmegaMan 可能是的,我会看看我能不能把它拆掉。它是一个 32 位非托管调用应用程序,并且没有手动创建线程。

标签: c# wpf


【解决方案1】:

您链接的文档在其备注部分中说明了以下内容:

每个应用程序类只能创建一个实例 AppDomain,确保对单个集合的共享访问 应用程序范围的窗口、属性和资源数据。最后, Application 类的无参数构造函数检测正在初始化的实例是否是第一个实例 应用域;如果不是,则抛出 InvalidOperationException。

我突出显示的部分意味着它不是检查它是否是当前运行的唯一/单个应用程序,而是检查之前是否已初始化任何另一个 Application 实例(无论它是否已关闭但是)。

查看source code of the Application class 可以证实这一点:Application 类在内部使用了一个静态标志 (_appCreatedInThisAppDomain),该标志仅在初始化第一个 Application 实例时设置一次。但显然这个标志永远不会重置,这会阻止您在同一个 AppDomain 中创建更多 Application 实例。

【讨论】:

  • 感谢您挖掘它,我不知道内部情况。所以我觉得 .Current 属性被重置为 null...
  • 是的,.Current 返回在 DoShutdown() 中设置为 null 的 _appInstance。
【解决方案2】:

这在 WinForms 中很容易,而在 WPF 中则不然。

显然,我们没有Application 问题,我们有AppDomain 问题。

我为此付出了合理的努力,但无法让它按我想要的方式运行,即销毁旧的然后在按下空格键时在新的Thread 上重新创建一个AppDomain ,我认为尽管有范围,但这是有道理的。

这充其量只是一种解决方法,在您的情况下甚至可能不是一个选择。

还有其他方法可以手动管理Current 的生命周期吗? 对象?

据我所知,简单的答案是在程序的整个生命周期内(通过 ShutdownMode.OnExplicitShutdown)维护 WPF 消息循环 Thread,并根据需要使用 Application.Current.Dispatcher 显示 WPF 对象。

这是我的意思的示例,在托管控制台应用程序中实现:

class Program
{
    static void Main(string[] args)
    {
        Thread t = CreateThread();

        t.Start();

        bool quit = false;
        while (!quit)
        {
            switch(Console.ReadKey().Key)
            {
                case ConsoleKey.Escape:
                    Application.Current.Dispatcher.Invoke(() => Application.Current.Shutdown());
                    quit = true;
                    break;
                case ConsoleKey.W:
                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        var w = new Window() { Width = 500, Height = 500, Title = "WPF Window" };
                        w.Show();
                    });
                    break;
                case ConsoleKey.D:
                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        var d = new Window() { Width = 500, Height = 500, Title = "WPF Dialog" };
                        d.ShowDialog();
                    });
                    break;
                case ConsoleKey.Spacebar:
                    //// Nope!
                    //Application.Current.Dispatcher.Invoke(() => Application.Current.Shutdown());
                    //t = CreateThread();
                    //t.Start();
                    break;
            }
        };
    }

    static Thread CreateThread()
    {
        var t = new Thread(() =>
        {
            if (System.Windows.Application.Current == null)
            {
                new System.Windows.Application();

                Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
            }

            Application.Current.Run();
        });
        t.SetApartmentState(ApartmentState.STA);

        return t;
    }
}

您需要参考 PresentationCore、PresentationFramework 和 WindowsBase 来构建此示例。

我希望它至少能激励某人。

编辑:仅供参考,这可能不再起作用了...当我发布它时它起作用了,现在两天后它不起作用。昨天安装了 .NET Framework (kb4538122) 的累积更新,但我不确定这是否是重大更改。

编辑:我更新了代码,现在又可以使用了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-05
    • 1970-01-01
    • 2017-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多