Frage

Ich zeige einen Begrüßungsbildschirm auf einem Hintergrund -Thread, während mein Programm geladen wird. Sobald es geladen bin, fällt ich den Thread ab, da es nur Zweck war, eine jetzt Ladungsausstattung zu zeigen.

Mein Problem ist, dass beim Abtreiben eines Faden ThreadAbortException dass der Benutzer einfach weiter klicken kann.

Wie gehe ich damit um? Ich habe versucht, es so zu unterdrücken ->

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

        }

Aber ich habe das Gefühl, dass ich hier anschreien und es nicht funktioniert.

Vielen Dank!

War es hilfreich?

Lösung

Sie müssen den Thread nicht stornieren. Ich werde mit Code veranschaulichen.

In der Schildschirmeform:

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

In der Datei program.cs:

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

Wenn Ihre Hauptmethode nun beginnt, zeigen Sie den Spritzer in einem Thread:

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

t.Start();

... und wenn du willst, dass es schließt, schließe es einfach:

Program.CloseSplash();

Dann müssen Sie sich keine Sorgen machen, den Thread abzubrechen. Es wird anmutig verlassen.

Andere Tipps

Weitere Informationen finden Sie im folgenden Link, der eine Google -Suche durchgeführt hat (erstes Ergebnis zurückgegeben):

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

Achten Sie auf diesen Teil besondere Aufmerksamkeit:

Wenn diese Methode auf einem Thread aufgerufen wird, wirft das System a Threadabortexception im Faden, um es abzubrechen. Threadabortexception ist eine besondere Ausnahme, die vom Anwendungscode erfasst werden kann, wird jedoch am Ende des Fangblocks nicht erzielt werden, es sei denn Resetabort wird genannt. Resetabort Storniert die Anfrage zum Abbruch und verhindert die Threadabortexception vom Beenden des Fadens. Es werden ungeschrieben schließlich Blöcke ausgeführt, bevor der Thread abgebrochen wird.

Die Verwendung von Threadabort wird nicht empfohlen. Es ist böse. Warum nicht einen anderen Mechanismus wie ein (automatisches/manuelles) ResetEvent verwenden? Starten Sie den Faden mit dem Splash-Screen und warten Sie auf der Veranstaltung. Wenn der andere Code geladen ist, laden Sie das Ereignis ein, um den Splash-Bildschirm die normale (schöne) Weise zu schließen.

Ein paar Punkte. Die Threadabort -Ausnahme ist der Grund, warum der Thread abbricht. Es ist kein Nebeneffekt, dass Sie abortieren. Wenn Sie Abbruch in einem Thread anrufen, erzwingt die Laufzeit eine Threadabort -Ausnahme, die an den Thread propagiert werden soll. Diese Ausnahme kann gefangen werden, da der Benutzer eine Reinigung durchführen kann, bevor der Thread abbricht.

Die Ausnahme wird dann automatisch überlegt, um sicherzustellen, dass der Thread abgebrochen wird. Wenn die Ausnahme gefangen würde und sie nicht überlegt würde, würde der Thread niemals abbrechen.

Wirklich intelligentes Design eigentlich.

Es ist also wirklich in Ordnung, diese Ausnahme zu fangen. In der Tat sollten Sie. Aber fangen Sie nur diese spezifische Ausnahme und nicht die allgemeine Ausnahme. (Wie nachfolgend dargestellt)

catch(ThreadAbortException ex)
{
   //This is an expected exception. The thread is being aborted
}

Ändern Sie den Ausnahmetyp in Threadabortexception und fügen Sie einen Anruf hinzu, um Resetabort ()

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

Im Allgemeinen wird abgebrochenes Threads als sehr schlechte Praxis angesehen und kann zu allen möglichen Schwierigkeiten führen. Haben Sie darüber nachgedacht, einen Weg zu finden Schließen Sie das Schlossfenster Oder verwenden Sie irgendeine Art von Umfragen Um den Thread zu stoppen, wenn eine Flagge eingestellt wurde?

Warum würdest du das tun? Stellen Sie einfach eine Flagge ein, die der Thread befragt, und dann schließlich, wenn der Thread es aufnimmt, schließt sich selbst.

Probieren Sie diesen Code aus. Es funktioniert gut für mich.

void splash()
{
    try {
        SplashScreen.SplashForm frm = new SplashScreen.SplashForm();
        frm.AppName = "HR";

        Application.Run(frm);
    }
    catch (ThreadAbortException ex)
    {
        Thread.ResetAbort();
    }
}

Ich habe die von Fredrik Mörk vorgeschlagene Lösung verwendet. Es ist sehr klar und elegant. Andernfalls fand ich ein Problem, wenn wir das Spritzformular vor dem Start der realen Anwendung (application.run (MainForm ...)) instanziieren:

Es erhöht eine ungültige OPRATIONException, die durch den Formhandel verursacht wird, der im Berufungsthread noch nicht vorhanden ist. Um den Griff direkt im Thread T zu erstellen (und diese Ausnahme überspringen!) Versuchen Sie, das Splash -Formular auf diese Weise zu starten:

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

t.Start();

Wenn Sie planen, die ClossPlash -Methode in mehr Zweigen des Programms aufzurufen, erzwingen Sie den Nullwert nach dem ersten Anruf:

    private static Splash _splash = null;
    public static void CloseSplash()
    {
        if (_splash!= null)
        {
            _splash.CloseSplash();
            _splash=null;
        }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top