6

私はいくつかのC#Winforms / WPFコードで少し遊んでいて、何か奇妙なことに遭遇しました。私がこのようなコードを持っているとしましょう:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DoSomething();

        // maybe something more if everything went ok
    }
}

私が困惑しているのは、コンストラクターがジョブを終了する前に、メソッドDoSomethingからアプリケーションを単純に閉じることができないことです。実行中に何かがDoSomething失敗した場合は、すぐにアプリケーションを閉じる必要がありますが、アプリケーションは実行を続け、パーツ// maybe something more...を実行してから閉じますが、それでは遅すぎます。

フォームを閉じるためのコードをコンストラクター自体の中に次のように配置return;する必要があります。そうすれば機能しますが、それが受け入れられる解決策ではありません。このような検証ロジックをコンストラクターからメソッドに移動しようとしています。

私は次のようなことを試みました

public void DoSomething()
{
    Close();
}

また

public void DoSomething()
{
    Application.Current.Shutdown();
}

しかし、それは機能していないようです。はい、どちらのコードもアプリケーションを閉じますが、コンストラクターコードが完全に完成した後でのみです。

Why私はそのようなものが必要でしょうか?起動時に、接続やハードウェアの可用性、ユーザーの検証など、さまざまなことを確認する必要があるため、何かが失敗した場合は、それ以上コードを実行する意味がありません。

WinformsとWPF(したがってタグ)で同じ原理を試しましたが、同じように機能します。

誰かが説明やおそらく解決策を提供できますか?

4

7 に答える 7

8

Environment.Exit(-1)あなたの状況で使用してみてください、そしてすべてがうまくいくでしょう。

追加: これは私があなたのために得ることができる最高のリファレンスです。

vsの違いApplication.ExitApplication.ShutdownEnvironment.Exit

Application.Exit()優雅な方法でWindowsフォームアプリケーションを終了するためのものです。基本的に、メッセージポンプを停止し、すべてのウィンドウを閉じて、Application.Run()の呼び出しの直後にMain()メソッドに戻ります。ただし、機能していないように見える場合があります。これは通常、スレッドの終了を妨げている他のフォアグラウンドスレッド(UIスレッドを除く)がまだ実行されているためです。

Application.Shutdown()(大まかに)WPFアプリケーションのApplication.Exit()と同等です。ただし、メインウィンドウが閉じたとき、最後のウィンドウが閉じたとき、またはこのメソッドが呼び出されたときにのみアプリケーションがシャットダウンするようにShutDownModeを設定できるため、もう少し制御できます。

Environment.Exit()実行中のすべてのスレッドを強制終了し、プロセス自体が完全に停止します。これは、WFまたはWPFで、より適切な方法が何らかの理由で機能しない場合の最後の手段としてのみ使用する必要があります。また、コンソールアプリケーションを突然終了するためにも使用できます。

別のリファレンス:C#アプリケーションを適切に終了する方法は?

于 2012-11-10T09:27:01.753 に答える
3

いつでも仲間の開発者を無視して、Environment.FailFast()を使用することができます

しかし、実際には-しないでください。重要なことを行う必要がある場合は、シリアルポートが原子力発電所に接続されていることを確認するSAが、事前に行ってください。Application.Run(...)呼び出されたらすぐに強制するルールはありませんMain()

于 2012-11-10T09:25:00.723 に答える
1

あなたの問題に対する実行可能な解決策はすでに投稿されています。

フォローアップの質問に答えるだけです。Close()やShutdown()などのメソッドがアプリケーションをすぐに終了しない理由は、どちらもメッセージをアプリケーションのメッセージキューにプッシュするだけだからです。これらは、MainWindowのコンストラクターが終了し、コードの実行がメッセージ処理ループに戻った後でのみ処理されます。おそらく、キュー内の他の保留中のメッセージも処理された後です。それどころか、Environment.Exit()やEnvironment.FailFast()のようなメソッドは、多かれ少なかれすぐにプロセスを強制終了するハードコアOS関数の一種です。

于 2012-11-10T12:38:13.690 に答える
0

回避策は、例外をスローして、それを処理することです。application.UnhandledException

于 2012-11-10T09:21:11.180 に答える
0

例外クラスを定義します。

public class InitializationException : Exception
{
    public InitializationException()
    {}

    public InitializationException(string msg)
        : base(msg)
    {}

    public InitializationException(string msg, Exception inner)
        : base(msg, inner)
    {}
}

次のようにコードを変更します。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        try
        {
            DoSomething();

            // maybe something more if everything went ok
        }
        catch( InitializationException ex )
        {
            // log the exception
            Close();
        }
    }

    public void DoSomething()
    {
        if (notSomethingOK)
            throw new InitializationException( "Something is not OK and the applicaiton must shutdown." );
    }
}

これは、クリーンで保守可能なソリューションです。

于 2012-11-10T09:29:09.737 に答える
0
System.Windows.Forms.Application.Exit();
于 2016-01-29T08:03:12.140 に答える
0

概念的には、そのようなものはクラスコンストラクターでは使用しないでください。コンストラクターは、たとえば開始状態での初期化のためにいくらか作成されており、実際には発生しない可能性があります(例外、メッセージボックスなど)。

ただ戻ることができることを忘れないでください。実行を中断する必要がある場合は、コンストラクターから。これはより良い戦術です(ほとんどの場合、テキストを表示せずにエラー時にアプリケーションをシャットダウンする必要はありません)。

Windows / WPFのC#には、「ウィンドウ表示」、「可視性の変更」、「読み込み済み」などの多くのイベントがあり、仮想的にオーバーライドしたり、イベントハンドラーとして追加したりできます。そこでフォーム/アプリを初期化します。

これらは通常の方法であるため、すべて期待どおりに機能します。アプリケーションのエントリポイント(メイン関数)がキャッチして無視する例外をスローしてみることができます。

WPFの場合は、次を確認してください。- https ://msdn.microsoft.com/en-us/library/system.windows.forms.application.setunhandledexceptionmode(v=vs.110).aspx 。

于 2016-01-29T08:17:08.997 に答える