PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : c# und der destruktor


Gnafoo
2004-11-25, 18:30:02
Hiho

Ich habe mal eine Frage bezüglich folgendem Code in c#:

using System;
using System.IO;
using System.Threading;

namespace TestApp
{
class TestClass
{
~TestClass()
{
for( int i = 0; i < 100000; ++i )
Console.WriteLine( "{0}", i );

StreamWriter a = new StreamWriter( new FileStream( "test.out",
FileMode.OpenOrCreate, FileAccess.Write ) );

a.WriteLine( "done" );
a.Close();
}
}

public class Application
{
static private void TestFunc()
{
TestClass a = new TestClass();
}

static public void Main()
{
TestFunc();
}
}
}

Das Programm bricht irgendwo um die 42.000 bei der Schleife im Destruktor ab.
Die Datei wird nicht geschrieben. Nehme ich die Schleife raus, wird die Datei tadellos
geschrieben.

Weil ich nichts dazu finden konnte, frage ich einfach mal hier: Hat c# da eine Art Erkennung
für infinite loops oder so etwas ? Ist die Ausführzeit von Destruktoren begrenzt ?

Ich habe damit in einem anderen Code ein Problem, weil einfach abgebrochen wird.

Vielen Dank im Vorraus
cya DerTod

Demirug
2004-11-25, 18:52:40
Genau sagen warum es nicht funktioniert kann ich dir nicht aber solcher Code gehört bei C# auf jeden Fall nicht in den Destruktor. Bei C# (und .net im allgemeinen) sollte man eigentlich gar keine Desturktoren benutzen.

Meine vermutung warum es nicht funktioniert ist folgenden.

Der Desktruktor wird ja vom GC aufgerufen um Probleme zu verhindern hat dieser wahrscheinlich ein Zeitlimit. Ist dieses erreicht kommt es zu einem Abbruch.

Gnafoo
2004-11-25, 19:06:03
Ja klar .. der Code hier ist eigentlich nur zum testen, bzw. um die Situation etwas zu abstrahieren. In meinem eigentlichen Programm wollte ich im Destruktor eigentlich einen Thread mit Abort abbrechen und warten, bis dieser abgeschlossen ist.
Während dem Warten auf den Thread scheint c# den Destruktor allerdings abzubrechen.

Meine erste Vermutung war, dass der GC den Destruktor weiterhin im Hintergrund ausführt, während die Anwendung schon beendet wurde und deswegen nichts ausgegeben wird. Deshalb hab ich versucht in eine Datei zu schreiben. Aber daran scheint es wohl nicht zu liegen.

Hm ein Zeitlimit für den Destruktor fände ich trotzdem komisch. Da wäre ja dann auch immer die Frage, wie schnell der Computer den Code abarbeiten kann.

cya DerTod

beta3
2004-11-25, 20:16:15
wenn du wirklich alles im Destruktor ablaufen lassen willst, benutze

System.GC.WaitForPendingFinalizers();


aber benutze es vorsichtig und nicht zu oft

Demirug
2004-11-25, 20:16:25
Ganz schlechte Idee weil der Ausführungszeitpunkt eines Destruktors beliebig ist. Wenn der GC meint das noch genügend Speicher da ist kann sich das wirklich bis zum Ende des Programms verzögern.

beta3
2004-11-25, 20:29:12
der GC wird ja aufgerufen, wenn das Objekt aus dem Scope ist und nicht mehr verwendet wird.

Ausserdem kann man immernoch selber Dispose aufrufen (falls man es implementiert hat)

Demirug
2004-11-25, 20:32:16
der GC wird ja aufgerufen, wenn das Objekt aus dem Scope ist und nicht mehr verwendet wird.

Nein, der GC wird irgendwann aufgerufen und entfernt dann einen Teil oder alle Objekte die nicht mehr im Scope sind.

Ausserdem kann man immernoch selber Dispose aufrufen (falls man es implementiert hat)

Ja, so sollte man das auch eigentlich machen.

Gnafoo
2004-11-25, 22:03:30
Das heißt um irgendwo aufzuräumen sollte ich eher Dispose benutzen ? Dann funktioniert das allerdings nicht mehr automatisch.
Mir ging es eigentlich eher darum, dass der betroffene Thread auch automatisch korrekt beendet wird. Wie macht man so etwas richtig ?

cya DerTod

grakaman
2004-11-25, 23:25:38
Das heißt um irgendwo aufzuräumen sollte ich eher Dispose benutzen ? Dann funktioniert das allerdings nicht mehr automatisch.
Mir ging es eigentlich eher darum, dass der betroffene Thread auch automatisch korrekt beendet wird. Wie macht man so etwas richtig ?

cya DerTod

Doch, wenn du in C# die using Anweisung verwendest. Wenn du mit Dispose arbeitest und trotzdem noch einen Finalizer benutzt und die Dispose Methode von deinem Programm aber zuerst aufgerufen wird, dann sollte die auch gleich den GC für das Objekt unterdrücken. Wenn sie nicht aufgerufen wird, dann wird der Finalizer ausgeführt. So sollte das zumindest Designtechnisch gestaltet werden.

grakaman
2004-11-25, 23:40:43
Ich habe dein Programm auch mal ausprobiert und vermute ebenfalls wie Demirug, dass der Finalizer einfach zu lange dauer und er deswegen abbricht.
Bei mir zählt er nämlich schon hoch, aber nur so bis 80.000 und noch was, danach bricht er ab. Wenn ich aber nur bis 10 gehe, dann wird auch die out Datei geschrieben. Das ist eigentlich auch logisch, denn wenn du das z.B. in einem anderen Thread laufen lassen würdest, dann würde der damit die ganze Zeit die anderen blockieren.