PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C#: Wie beende ich richtig einen Thread


Elemental
2004-05-12, 12:37:17
Beim Start meines Programmes zeige ich für 5 Sekunden einen Splashscreen an:


//show Splashscreen
m_Splasher = new Splashscreen();
m_SplashScreenThread = new System.Threading.Thread( new System.Threading.ThreadStart( StartSplashScreen ) );
m_SplashScreenThread.Priority = System.Threading.ThreadPriority.Normal;
m_SplashScreenThread.Start();

//create a timer
m_Timer = new System.Windows.Forms.Timer();
m_Timer.Tick += new EventHandler(TimerEventProcessor);
// Sets the timer interval to 5 seconds.
m_Timer.Interval = 5000;
m_Timer.Start();



Wenn der Timer abgelaufen ist, beende ich den Splashscreen:

private void TimerEventProcessor(Object myObject, EventArgs myEventArgs)
{
//this call of Activate() is important at this position, because otherwise the main window won't be in front
this.Activate();

m_Timer.Stop();
m_Splasher.Close();
m_SplashScreenThread.Abort();
}



Der Code funktioniert eigentlich fast immer, nur manchmal kommt es zu einer ThreadAbortException, wenn der Splashscreen beendet wird. Ich kann das nicht wirklich reproduzieren.

Da ist doch kein Fehler, oder? Sollte man einen Thread nicht mit Abort() beenden?


mfG
Elemental

ScottManDeath
2004-05-12, 13:37:42
Mit Thread.Join() kannst du den aufrufenden Thread blockieren bis der aufgerufene Thread beendet ist. Du müsstest das nach deinen Aufruf von Thread.Abort machen.

Elemental
2004-05-12, 13:46:50
Original geschrieben von ScottManDeath
Mit Thread.Join() kannst du den aufrufenden Thread blockieren bis der aufgerufene Thread beendet ist. Du müsstest das nach deinen Aufruf von Thread.Abort machen.

Und das beseitigt die ThreadAbortException?

ethrandil
2004-05-12, 14:16:27
Ich finde das ganze auf die Art und Weise ein bisschen unschön.

Wieso musst du deinen Thread überhaupt beenden? [jaja, cih komme aus der Java-Ecke] Befindet sich in deinem Thread eine Schleife, oder geht es nur darum den SplashScreen zu löschen (sammt Thread)?

- Eth

Elemental
2004-05-12, 14:31:17
Geht nur darum, den SplashScreen weg zu hauen.
Was passiert, wenn ich den thread nicht explizit beende?
Läuft der ewig weiter?

ethrandil
2004-05-12, 14:35:58
Original geschrieben von Elemental
Was passiert, wenn ich den thread nicht explizit beende?
Läuft der ewig weiter?
Ich dneke nicht.

Wenn die Thread-methode durchgelaufen ist, und keine weiteren Objekte im Thread gehalten werden wird er irgendwann von der GarbageCollection eliminiert.

Ich würde nicht den Thread beenden, sondern einfach nur den Splashscreen löschen.

- Eth

Gugu
2004-05-12, 14:37:17
Bevor du den Thread beendest, solltest du prüfen, ob er überhaupt noch läuft:


if(m_SplashScreenThread.IsAlive)
m_SplashScreenThread.Abort();


Und musst du hier
m_Splasher.Close();
m_SplashScreenThread.Abort();
nicht zuerst den Thread beenden, bevor du das Fenster schließt? Also:
if(m_SplashScreenThread.IsAlive)
m_SplashScreenThread.Abort();
m_Splasher.Close();

Elemental
2004-05-12, 14:46:39
Original geschrieben von Gugu
Und musst du hier
m_Splasher.Close();
m_SplashScreenThread.Abort();
nicht zuerst den Thread beenden, bevor du das Fenster schließt? Also:
if(m_SplashScreenThread.IsAlive)
m_SplashScreenThread.Abort();
m_Splasher.Close();


Hmmm. Muss ich das Fenster überhaupt noch beenden, wenn ich vorher schon den Thread, in welchem das Fenster läuft, beende?

ethrandil
2004-05-12, 14:51:15
Original geschrieben von Elemental
Hmmm. Muss ich das Fenster überhaupt noch beenden, wenn ich vorher schon den Thread, in welchem das Fenster läuft, beende?
ALso ich schätze jetzt mal ;-)

a) Wenn du den Thread schließt, dann wird alles enthaltene gekillt (das ist in java nicht so, aber evtl. in c#)
b) Wenn du das Fenster beendest wird der Thread automatisch gekillt.

also ich würde nur das Fenster killen, und den Thread so lassen wie er ist.
Wenn man das Fenster quasi killt ist das so rabiat ;), das ist bestimmt irgendwie unschön...

- Eth

Elemental
2004-05-12, 14:52:10
Original geschrieben von ethrandil
Ich dneke nicht.

Wenn die Thread-methode durchgelaufen ist, und keine weiteren Objekte im Thread gehalten werden wird er irgendwann von der GarbageCollection eliminiert.

Ich würde nicht den Thread beenden, sondern einfach nur den Splashscreen löschen.

- Eth

Was genau meinst du mit löschen?

Reicht ein


m_Splasher.Close();


oder doch lieber


m_Splasher.Close();
m_Splasher = null;


oder ganz anders?


mfG
Elemental

ethrandil
2004-05-12, 14:53:49
m_Splasher.Close();
m_Splasher = null;

müsste ausreichen.

Am Besten du löst es erstmal so und wartest bis ein c#-Profi hier auftaucht und dir sagt wie mans besser macht ;)

Ansonsten dürfte das reichen.

- Eth

Elemental
2004-05-12, 14:55:33
Original geschrieben von ethrandil
würde nur das Fenster killen, und den Thread so lassen wie er ist.
Wenn man das Fenster quasi killt ist das so rabiat ;), das ist bestimmt irgendwie unschön...

- Eth


Du meinst den Thread killen is so rabiat, oder?

ScottManDeath
2004-05-12, 15:15:11
So aus dem Bauch heraus würde ich eine SplashScreen Klasse machen die einen Timer enthält. Wenn das Timer Event getriggert hat einfach this.Close() aufrufen.

In der Main Methode dann einen neuen Splash Screen erstellen und anzeigen.


static void Main()
{
try
{
SplashScreen splash = new SplashScreen();
splash.Show();

MainForm f = new MainForm();
f.Show();

while(f.IsCreated)
{
f.Render();
Application.DoEvents();
}

//Application.Run(new MainForm());
}
catch (Exception e)
{
MessageBox.Show(null,e.Message,"Error");
}
}

ethrandil
2004-05-12, 15:44:18
Original geschrieben von Elemental
Du meinst den Thread killen is so rabiat, oder?
Ja, aber ich kenn mich speziell bei c# nicht aus. nur theoretisch ;-)

- Eth

MeLLe
2004-05-12, 18:04:25
Original geschrieben von ScottManDeath
So aus dem Bauch heraus würde ich eine SplashScreen Klasse machen die einen Timer enthält. Wenn das Timer Event getriggert hat einfach this.Close() aufrufen.

In der Main Methode dann einen neuen Splash Screen erstellen und anzeigen.


Genau so würde ich das auch machen, denn dann braucht man den gestarteten Thread nicht vom Main aus killen - was wirklich etwas rabiat ist ;) - sondern er verwaltet sich und sein Ableben selbst!

ScottManDeath
2004-05-12, 19:09:41
Es ist ausserdem noch empfehlenswert zwischen dem splash.Show() und dem Application.Run(new MainForm()) noch ein Application.DoEvents() einzufügen damit das splash window schon vor der MainForm angezeigt wird.

Elemental
2004-05-12, 21:36:23
Original geschrieben von ScottManDeath
Es ist ausserdem noch empfehlenswert zwischen dem splash.Show() und dem Application.Run(new MainForm()) noch ein Application.DoEvents() einzufügen damit das splash window schon vor der MainForm angezeigt wird.

Ich hab das Zeug mit SplashScreenThread und Timer starten im Konstruktor von meinem MainForm, vor dem InitializeComponent() :D

Elemental
2004-05-14, 10:59:56
Hab jetzt mal


m_Splasher.Close();
m_Splasher = null;


eingebaut und den Abort() Aufruf auskommentiert.

Beim debuggen sieht man jetzt im taskmanager sehr schön, dass sobald m_Splasher auf null gesetzt wird, die Threadanzahl um 1 verringert wird
:)


mfG
Elemental