5

プログラムのロード中にバックグラウンド スレッドにスプラッシュ スクリーンを表示しています。ロードしたら、スレッドを中止します。唯一の目的は Now Loading スプラッシュ フォームを表示することだったからです。

ThreadAbortException私の問題は、スレッドを中止すると、ユーザーが [続行] をクリックするだけでスローされることです。

どうすればこれに対処できますか? みたいに抑えようとしてたのに -->

            try
        {
            Program.splashThread.Abort();
        }
        catch(Exception ex)
        {

        }

しかし、ここで怒鳴られそうな気がして、うまくいきません。

ありがとう!

4

8 に答える 8

20

スレッドをキャンセルする必要はありません。コードで例を挙げます。

スプラッシュ画面フォーム:

public void CloseSplash()
{
    Invoke((MethodInvoker)delegate
    {
        this.Close();
    });
}

Program.cs ファイル内:

private static Splash _splash = null;
public static void CloseSplash()
{
    if (_splash!= null)
    {
        _splash.CloseSplash();
    }
}

ここで、Main メソッドが開始されたら、スレッドにスプラッシュを表示します。

Thread t = new Thread(new ThreadStart(delegate
{
    _splash = new Splash();
    _splash.ShowDialog();
}));

t.Start();

...そして、閉じたいときは、閉じてください:

Program.CloseSplash();

その後、スレッドの中止について心配する必要はありません。それは優雅に終了します。

于 2009-06-04T14:59:36.193 に答える
9

Google 検索を実行して取得した次のリンクを参照してください (最初の結果が返されます)。

http://msdn.microsoft.com/en-us/library/5b50fdsz.aspx

この部分に特に注意してください。

このメソッドがスレッドで呼び出されると、システムはスレッドでThreadAbortExceptionをスローしてスレッドを中止します。ThreadAbortExceptionは、アプリケーション コードでキャッチできる特別な例外ですが、ResetAbortが呼び出されない限り、catch ブロックの最後で再スローされます。ResetAbortは中止要求をキャンセルし、ThreadAbortExceptionがスレッドを終了させないようにします。未実行の finally ブロックは、スレッドが中止される前に実行されます。

于 2009-06-04T14:52:17.443 に答える
7

Threadabort の使用はお勧めしません。それは悪です。(自動/手動)ResetEvent のような別のメカニズムを使用しないのはなぜですか? スプラッシュスクリーンでスレッドを開始し、イベントを待ちます。他のコードが読み込みを完了したら、イベントを設定して、スプラッシュ スクリーンを通常の (適切な) 方法で閉じることができるようにします。

于 2009-06-04T14:53:01.870 に答える
4

例外タイプをThreadAbortExceptionに変更し、 ResetAbort()への呼び出しを追加します。

    try
    {
        Program.splashThread.Abort();
    }
    catch(ThreadAbortException ex)
    {
        Thread.ResetAbort();
    }

一般に、スレッドの中止は非常に悪い習慣と見なされており、あらゆる種類の追跡が困難なバグにつながる可能性があります。スプラッシュ ウィンドウを閉じる方法や、フラグが設定されているときに何らかのポーリングを使用してスレッドを停止する方法を考えたことはありますか?

于 2009-06-04T14:50:35.510 に答える
4

いくつかのポイント。ThreadAbort 例外は、スレッドが中止される理由です。中止を呼び出すことの副作用ではありません。スレッドで中止を呼び出すと、ランタイムは強制的に threadabort 例外をスレッドに伝達します。この例外は、スレッドが中止される前にユーザーがクリーンアップを実行できるため、キャッチできます。

その後、スレッドが確実に中止されるように、例外が自動的に再スローされます。例外がキャッチされ、再スローされなければ、スレッドは決して中止されません。

実際には本当にインテリジェントなデザイン。

したがって、その例外をキャッチしても問題ありません。実際、あなたはすべきです。ただし、一般的な例外ではなく、その特定の例外のみをキャッチします。(下図参照)

catch(ThreadAbortException ex)
{
   //This is an expected exception. The thread is being aborted
}
于 2009-06-04T18:10:54.410 に答える
1

どうしてそうするか?スレッドがポーリングするフラグを設定するだけで、最終的にスレッドがそれを取得すると、それ自体が閉じます。

于 2009-06-04T14:52:59.907 に答える
0

Fredrik Mörk が提案したソリューションを使用しました。とてもクリアでエレガントです。それ以外の場合、実際のアプリケーション (application.run (mainform...)) を起動する前にスプラッシュ フォームをインスタンス化すると、問題が見つかりました。

呼び出し側スレッドにフォームハンドルがまだ存在しないために発生する invalidOprationException を発生させます。スレッド t でハンドルを直接作成するには (そしてこの例外をスキップします!)、次の方法でスプラッシュ フォームを起動してみてください。

Thread t = new Thread(new ThreadStart(delegate
{
    _splash = new Splash();
     Application.Run(_splash);
}));

t.Start();

また、プログラムのより多くのブランチで closeSplash メソッドを呼び出す予定がある場合は、最初の呼び出しの後に null 値を強制します。

    private static Splash _splash = null;
    public static void CloseSplash()
    {
        if (_splash!= null)
        {
            _splash.CloseSplash();
            _splash=null;
        }
}
于 2009-07-23T14:11:06.963 に答える