Laden...

Wie kann sichergestellt werden, dass Dispose auch bei Fehlern aufgerufen wird? [==> using]

Erstellt von gelöschtem Konto vor 15 Jahren Letzter Beitrag vor 15 Jahren 2.066 Views
Hinweis von gfoidl vor 12 Jahren

Abgeteilt von Dispose implementieren und verwenden (IDisposable)

Gelöschter Account
vor 15 Jahren
Wie kann sichergestellt werden, dass Dispose auch bei Fehlern aufgerufen wird? [==> using]
  1. wie sieht es denn eigendlich mit objekten aus, die idisposable implementieren, in einem thread verwendet werden und innerhalb eines usings gerde sind?

wenn der thread seine abarbeitung plötzlich abbricht, wird dann dispose trotzdem noch aufgerufen?

  1. noch etwas:
    sehr oft sieht man

//objekt das Dispose implementiert instanziieren...
myDisplosableObject o = new myDisplosableObject();
//... einige operationen.
o.Dispose():

wie wird es da gehandhabt, wenn der abbruch mitten drinn eintritt?

meine vermutung: (ich brauch dafür aber noch eine bestätigung^^)
fall 1: dispose wird aufgerufen
fall 2: dispose wird nicht aufgerufen

wenn es sich aber nur um speicher handelt, dann wird er beim beenden des programmes dennoch freigegeben oder? wie sieht es denn mit unverwaltetem speicher aus? wird dieser auch beim beenden mit freigegeben?

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo JAck30lena,

wenn der thread seine abarbeitung plötzlich abbricht, wird dann dispose trotzdem noch aufgerufen?


using (MyDisposableObject mdo = new MyDisposableObject ()) {
   ...
}

ist m.E. äquivalent zu


{
   MyDisposableObject mdo = new MyDisposableObject ();
   try {
      ...
   }
   finally {
      mdo.Dispose ();
   }
}

Wenn du mit "Abbrechen" Thread.Abort und nicht Process.Kill meinst, wäre die Antwort also ja.

  
//objekt das Dispose implementiert instanziieren...  
myDisplosableObject o = new myDisplosableObject();  
//... einige operationen.  
o.Dispose():  
  

wie wird es da gehandhabt, wenn der abbruch mitten drinn eintritt?

Dispose wird dann nicht ausgeführt. Dabei ist es ganz egal welcher Art der Abbruch ist. Schon ein simples return würde die Ausführung von o.Dispose verhindern.

wenn es sich aber nur um speicher handelt, dann wird er beim beenden des programmes dennoch freigegeben oder?

Wenn Dispose richtig implementiert wird, werden die vom Objekt gehaltenen Ressourcen - egal welcher Art - im Zuge der Arbeit des GC mitfreigegeben und damit oft schon vor dem Beenden des Programms. Der GC ruft dabei den Destruktor auf und der eben Dispose.

BTW: Dispose gibt nur die vom Objekt gehaltenen Ressourcen frei. Dispose gibt nie den Speicher des Objekts selbst frei. Das kann nur der GC.

herbivore

Gelöschter Account
vor 15 Jahren

erstmal danke für die antworten.

in diesem fall:

wenn es sich aber nur um speicher handelt, dann wird er beim beenden des programmes dennoch freigegeben oder?

meinte ich eher folgendes szenario:

1.

//objekt das Dispose implementiert instanziieren...
myDisplosableObject o = new myDisplosableObject();
// hier ein abbruch durch abort.
o.Dispose(): 

innerhalb des dispose wird unverwalteter speicher freigegeben.
was macht der gc?
was passiert mit dem speicher nach beenden des prozesses?

S
8.746 Beiträge seit 2005
vor 15 Jahren

innerhalb des dispose wird unverwalteter speicher freigegeben.
was macht der gc?

Gar nix.

was passiert mit dem speicher nach beenden des prozesses?

Der wird in jedem Fall freigegeben. Dafür sorgt entweder der Finalizer oder - wenn der nicht aufgerufen wird - Windows selbst. Windows gibt seine eigenen (!) Ressourcen bei Prozessende frei.

Vorsicht ist nur geboten, wenn Ressourcen verwendet werden, die Windows nicht im Zugriff hat. Angenommen du hast eine Ressource auf einem entfernten Rechner allokiert, so geschieht hier natürlich nix automatisch. Hier musst du unter allen Umständen dafür sorgen, dass du solche Ressourcen korrekt via Finalizer abräumst und du mußt - soweit möglich - dafür sorgen, dass die Finalizer bei Prozessende aufgerufen werden.

Cooperative Application Shutdown with the CLR

Gelöschter Account
vor 15 Jahren

ok also der fall das man irgendwie "tote" speicherbereiche provozieren kann, die nur noch durch einen reboot wieder genutzt werden können, kann nicht eintreten.

schlussfogerung: alles was Dispose hat UNBEDINGT in ein using rein.

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo JAck30lena,

ok also der fall das man irgendwie "tote" speicherbereiche provozieren kann, die nur noch durch einen reboot wieder genutzt werden können, kann nicht eintreten.

richtig, spätestens beim Prozessende wird der gesamte Speicher der Prozesses freigegeben.

schlussfogerung: alles was Dispose hat UNBEDINGT in ein using rein.

Ich würde sagen: Alles was Dispose hat nach Möglichkeit in ein using rein. Denn using kann man nur dann benutzen, wenn das Objekt innerhalb des gleichen Codeblocks zerstört werden soll, in dem es erzeugt wurde. Nun gibt es aber auch bei Objekten, die Dispose implementieren, Situationen, in denen es besser ist, ein Objekt nur einmal zu Beginn des Programms zu erzeugen und erst am Ende zu zerstören. Zum Beispiel ist es besser einen Brush oder Pen nur einmal zu erzeugen und immer wiederzuverwenden, statt ihn im OnPaint per using jedesmal neu zu erzeugen und zu zerstören.

herbivore