【问题标题】:How can I declare a second, new Application object after the first has shut down?如何在第一个对象关闭后声明第二个新的 Application 对象?
【发布时间】:2018-04-17 20:44:52
【问题描述】:

这个问题与重新启动应用程序有关。

我看到了this 的问题。然而,这个问题,据我所知,答案已经有将近十年的历史了,而且似乎都没有提供这个特定问题的答案(如何定义第二个 Application 对象,一旦第一个有调用了它的.Shutdown 方法)。

在第一个调用其.Shutdown( ) 方法后尝试声明new App( ) 会导致以下异常:

我可以对原始的 App 对象做些什么来防止他发生吗?

符合Minimal, Complete and Verifiable Example要求:

确定App.xaml 的构建操作设置为Page

App.xaml.cs:

using System;

namespace MCVE {
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
    public partial class App {
        private static bool _isRestarting = true;
        public static bool IsRestarting {
            get => _isRestarting;
            set => _isRestarting = value;
        }

        [STAThread]
        public static void Main( ) {
            while ( IsRestarting ) {
                IsRestarting = false;
                App program = new App( );
                program.InitializeComponent( );
                program.Run( );
            }
        }
    }   
}

MainWindow.xaml:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    x:Class="MCVE.MainWindow"
    mc:Ignorable="d" Title="MainWindow" Height="450" Width="800">
    <UniformGrid Rows="1">
        <Button Content="Restart" Click="Restart" />
        <Button Content="Exit" Click="Shutdown" />
    </UniformGrid>
</Window>

MainWindow.Xaml.cs:

using System.Windows;

namespace MCVE {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window {
        public MainWindow( ) {
            InitializeComponent( );
        }

        private void Restart( object sender, RoutedEventArgs e ) {
            App.IsRestarting = true;
            Shutdown( sender, e );
        }

        private void Shutdown( object sender, RoutedEventArgs e ) =>
            Application.Current?.Shutdown( );
    }
}

要重现:单击显示Restart 的按钮。

【问题讨论】:

  • 您需要重新启动进程,而不仅仅是启动App 类的新实例。见Process.Start
  • @RonBeyer 好的。如果一个进程已由另一个进程启动,例如在 Visual Studio 中调试应用程序时 - 我如何将新进程移交给调用进程的“父”进程?但我想这应该是一个新问题......
  • System.Diagnostics.Debugger.Launch(),您可能需要将参数传递给新应用程序,以告知它以前附加了一个调试器。
  • @RonBeyer 假设我可以#if DEBUG 它来启动调试器,如果它没有连接的话......仍然感觉不太理想,但是嗯。任何。感谢您的提示。希望有一些更完美的答案。比如,如何清除关闭应用实例的AppDomain
  • 您无法“清除”基本 AppDomain,因为它无法卸载或“重置”。 “清除”(卸载)AppDomain 的唯一方法是创建一个新的,但不能替换默认值。

标签: c# wpf xaml restart shutdown


【解决方案1】:

Application 类被设计为只运行一次并与它所加载到的AppDomain 的生命周期相关联。即使你能找到一些方法来解决这个问题,这也违背了应该如何使用这个类的意图。 (见备注部分here。)

我建议不要与特定班级的既定意图抗争,而是退后一步,想想你想要完成什么。如果要重新启动整个应用程序,请考虑启动一个新进程。如果您想卸载然后重新加载一堆东西,请在单个 Application 实例范围内的适当级别将该功能构建到您的代码中。

根据您要完成的工作,您可能还需要考虑阅读AppDomain(可以开始here,但如果您四处搜索可能会有更好的资源)。 AppDomain 专门设计为一个封装的独立竞技场,您可以在其中通过加载和卸载整个域来加载和卸载一堆东西。

我相信也可以在每个域中运行Application 实例,但我从未尝试过这样的事情。如果您这样做,您可能应该避免在默认域中运行 Application 实例,因为除非关闭进程,否则永远无法卸载该域。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-07
    • 1970-01-01
    • 2015-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-11
    • 2021-03-08
    相关资源
    最近更新 更多