Autor Beitrag
spass2000
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Di 29.08.06 21:19 
Hallo Forum und C# Gurus

Ich bin gerade etwas am verzweifeln...

Ich verwende ein managed assembly von einem dritt Anbieter. Eine Klasse dieses Assembly hat einen EventHandler. Nun kommt es vor das irgendwann und irgendwo in den untiefen dieses Assembly der GC zuschlägt und diese Klasse terminiert, sodass keine Events mehr kommen.
Nun sagt mir der schlaue Support ich solle dies mit KeepAlive absichern, obwohl ich hier ja nicht mit unmanged Code arbeite und ich ja eine Referenz auf das Event halte.

Also hab ich auf die schnelle zwei Klasse gebastelt eine in der ein Thread läuft und eine andere mit einem Timer und habe versucht diese mit

GC.Collect();
GC.WaitForPendingFinalizers();

zu killen. Leider ohne erfolgt. Mach ich jedoch dies mit dem gekauften Assembly fliegen die Fetzen. Also nehme ich mal stark an dass in diesem Assembly nicht alles korrekt abläuft. Also habe ich den Support vorgeschlagen ob man das nicht sauber mit einem IDisposable Interface und mit SuppressFinalize lösen könnte. Aber die Antwort von Support war nur: KeepAlive verwenden.

Was hält ihr von der Idee jedes Object, dass ein Event produziert mit KeepAlive abzusichern?

Danke für eure Mithilfe!


KeepAlive:
==========
The purpose of the KeepAlive method is to ensure the existence of a reference to an object that is at risk of being prematurely reclaimed by the garbage collector. A common scenario where this might happen is when there are no references to the object in managed code or data, but the object is still in use in unmanaged code such as Win32 APIs, unmanaged DLLs, or methods using COM.

Another case of premature garbage collection occurs when an object is created and used within a method. The object might be reclaimed while a call to one of its members is still executing, as shown in the first code example.

This method references obj, making that object ineligible for garbage collection from the start of the routine to the point, in execution order, where this method is called. Code this method at the end, not the beginning, of the range of instructions where obj must be available.

The KeepAlive method performs no operation and produces no side effects other than extending the lifetime of the object passed in as a parameter.
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mi 30.08.06 11:46 
user profile iconspass2000 hat folgendes geschrieben:
[...]obwohl ich hier ja nicht mit unmanged Code arbeite
Wie wird denn das Event ausgelöst? Wird es "von außen" ausgelöst, muss ja unmanaged Code im Spiel sein.
Zitat:
und ich ja eine Referenz auf das Event halte.

Falsch. Du hälst keine Referenz auf das Event, das Event hält eine Referenz auf deinen Eventhandler. Somit ist es vollkommen legal, wenn der GC das Objekt entsorgt.
Zitat:
Leider ohne erfolgt.
Dann hast du etwas falsch gemacht ;) . Wie gesagt, ein Objekt ohne Referenz wird gekillt, und Events sind keine Referenzen auf das Objekt. Gerade bei Timern kann man damit herrlich auf die Schnauze fallen, wenn man den Aufruf von Dispose vergisst.
Zitat:
Was hält ihr von der Idee jedes Object, dass ein Event produziert mit KeepAlive abzusichern?
Wenn es wirklich keine Referenz auf das Objekt gibt (ein richtig eingesetztes IDisposable-Objekt hat immer eine Referenz!), ist das die einzige Möglichkeit. du könntest zwar eine Dummy-Methode im Objekt implementieren, aber das läuft aufs gleiche hinaus.
spass2000 Threadstarter
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Mi 30.08.06 17:14 
Hallo Khabarakh

danke für dein Feedback

Diese Wrapper DLL (manged Code) löst ein Event aus, ich würde es mal mit einem Timer Event vergleichen, aber dieses Event wird definitiv unmanged erzeugt. Ich bekomme nach außen nur den event handler angeboten.

Auf diesen Event Handler hänge ich mich dann drauf, damit war ich eigentlich der Meinung, dass damit das Object nicht unter meinen Füßen weggezogen werden kann. Ich halte ja eine Referenz. (das war mein Irrglaube)

Warum kommt also der Optimizer auf die Idee das Object einfach in die Tonne zu werfen. Es muss ja für ihn so aussehen, als ob dieses Object nichts macht. Könnte man nicht SuppressFinalize verwenden, damit dies nicht passiert?

danke & Ciao
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Do 31.08.06 11:10 
user profile iconspass2000 hat folgendes geschrieben:
Diese Wrapper DLL (manged Code) löst ein Event aus, ich würde es mal mit einem Timer Event vergleichen, aber dieses Event wird definitiv unmanged erzeugt.
Na dann kannst du an KeepAlive wirklich nicht herummeckern ;) .
Zitat:
Warum kommt also der Optimizer auf die Idee das Object einfach in die Tonne zu werfen. Es muss ja für ihn so aussehen, als ob dieses Object nichts macht.
Der GC überprüft nicht, ob ein Objekt nichts macht, sondern ob es nicht gebraucht wird. Und da keine Referenz auf deine Instanz existiert, wird sie aus diesem Grund entsorgt.
Zitat:
Könnte man nicht SuppressFinalize verwenden, damit dies nicht passiert?
Das würde lediglich den Aufruf von Finalize verhindern, nicht aber die Garbage Collection. Nein, es gibt nur einen einzigen Weg zu verhindern, dass der GC ein Objekt als Garbage markiert und im nächsten Durchlauf entsorgt: Eine Referenz auf das Objekt halten. Es dürfte schon genügen, wenn du die Instanz beim Erzeugen irgendeinem Feld zuweist (das Objekt des Feldes sollte dann natürlich ebenfalls nicht zu früh in die Tonne getreten werden ;) ). Wenn du auf Nummer Ganzganzsicher gehen willst, kannst du die Referenz in einem statischen Feld speichern. Statische Felder werden vom GC als Root betrachtet und nur beim Schließen der AppDomain oder des Prozesses entsorgt.