Einzelnen Beitrag anzeigen

Robert_G
(Gast)

n/a Beiträge
 
#16

Re: Interfaces in DotNet ganz anders?

  Alt 4. Dez 2004, 01:28
Zitat von Fingolfin:
Zitat von Robert_G:
Da du in .Net die Referenzzählung nicht mehr selbst machen muss, sieht es auch gleich viel "aufgeräumter" aus.
Das verwirrt mich jetzt etwas. In Delphi besteht doch im Grunde keine Notwendigkeit selbst an der Referenzzählung rumzuspielen?!? Das käme eigentlich nur bei der Mischung von Interface- und Objektreferenzen zum Tragen und das habe ich immer vermieden, weil es eben so stark fehleranfällig ist.
Du hast dich selbst beantwortet.
Mit TInterfacedObject bekommst das Standardverhalten frei Haus. Aber wenn du dieses Objekt einmal als Interface benutzt kann es dir sehr schnell unter'm Hintern weggeklaut (==zerstört) werden.
Wenn man _Release selbst implementiert kann man es verhindern, aber da sich die Instanz selbst verwalten muss kann es ganz schön haarsträubend ausarten.

Zum Thema GC & Vertrauen:
Die GC funktioniert normalerweise absolut prima, aber es gibt Grenzfälle...
  • Die GC interessiert sich überhaupt nicht für unmanaged resources und ob diese eine Instanz einer managed Klasse referenzieren.
    Sie wird dir deshalb diese Instanz wegklauen, wenn sie von keiner anderen managed Instanz referenziert wird oder du ihr Leben nicht verlängerst.
    • Zum Beispiel mit GC.SupressFinalize/GC.ReRegisterForFinalize kannst du verhindern, dass die Instanz vorzeitig zerstört wird:
      Delphi-Quellcode:
      //verhindern, dass die Instanz zerstört wird
      GC.SupressFinalize(EineInstanz);
      //mache irgendwas...
      GC.ReRegisterForFinalize(EineInstanz);
      // ab jetzt kann die Instanz wieder von der GC zerstört werden
    • Sehr simpel ist KeepAlive, aber man kann es sicher nicht überall verwenden.
      Wenn du in einer Methode das da schreibst:GC.KeepAlive(EineInstanz); Dann weiß die GC, dass du mindestens bis zu diesem Punkt eine Referenz auf die Instanz bewahren willst.

      Delphi-Quellcode:
      SomeClass EineInstanz= new SomeClass();
      //irgend ein unmanaged call, der zum Bleistift EineInstanz als Parameter braucht...
      //und hier gleich noch einer...
      //ohne GC.KeepAlive könnte EineInstanz schon nach/während des ersten Calls tot sein
      GC.KeepAlive(EineInstanz);
      // ab jetzt kann die GC diese Instanz zerstören

  • Die GC läuft in allen Nicht-Service-Applications (hübsches Wort ) als Hintergrundthread.
    d.h.: Du hast gerade mit deinen 100MB an Sprites gespielt, nun machst du etwas anderes und erwartest, dass die GC aufräumt...
    Dumm ist nur, dass "etwas anderes" die CPU ziemlich beansprucht, "noch etwas anderes" die 2. CPU, ... außerdem hat dein System noch genügend RAM frei.
    Die GC sieht jetzt gar nicht ein warum sie der armen CPU den Stress des Aufräumens antun sollte. -> Sie wird also nicht aufräumen.
    Du weißt aber, dass du den Speicher gleich brauchen wirst. (Hellsehen ist eines der Dinge, die M$ noch nicht in die GC integriert hat -> kommt wohl in .Net 0815 )
    Deshalb kannst du die GC mit:GC.Collect(); ... dazu anweisen, zu sortieren.
    Wenn du erst dann weitermachen willst, wenn der Speicher frei ist:
    GC.WaitForPendingFinalizers(); Dadurch wird dein Thread pausiert bis alle Instanzen, die von der GC als NullReferenzen erkannt wurden, weg sind.
    Damit gehst du sicher, dass der Speicher frei ist, aber du hast kurzeitig den Performancegewinn durch einen automen "Aufräum-thread" aufgegeben.
    Diesen, etwas krassen Schritt, habe ich bisher immer wieder aus meinen Code entfernt, da es (nach ein paar Tests) einfach nicht notwendig war.
Zitat von Fingolfin:
Wenn jemand die vielleicht mal in einem Satz niederschreiben könnte, bezugnehmend auf meine Verwunderung, wäre ich überglücklich
War wohl doch mehr als ein Satz...
So jetzt kann es die Mieze zerreißen.
  Mit Zitat antworten Zitat