Hallo zusammen,
ich habe gerade ein Problem untersucht, bei dem ich nicht sicher bin, wie das zu bewerten ist:
Kunde baut eine Testanwendung (Consolen-Applikation) mit C# - dort bindet er über einen Verweis eine Siemens-DLL als COM-Objekt ein.
Aus der DLL instanziiert er jetzt ein Objekt über COM, im Process-Explorer sieht man, wie ein Prozess als untergeordneter Prozess der Consolenanwendung auf geht.
So weit so gut. Ohne sonst irgendwas mit dem Objekt zu machen ruft er jetzt Marshal.FinalReleaseCOMObject auf das Objekt auf.
Erwartung: Das Objekt wird frei gegeben und verschwindet aus Process-Explorer
Tatsächlich: Das Objekt ist zwar von C# aus nicht mehr ansprechbar, im Process-Explorer lebt der Prozess aber weiter.
Untersuchung des Prozesses im Process-Explorer zeigt jetzt unter View->Handles zwei noch laufende Threads an.
Meine Vermutung wäre jetzt, dass die Komponente intern schlampig programmiert ist und beim Aufruf von Release() nicht korrekt aufräumt. Kann man davon ausgehen, oder gibt es noch weitere Möglichkeiten?
Danke
Meine Vermutung wäre jetzt, dass die Komponente intern schlampig programmiert ist und beim Aufruf von Release() nicht korrekt aufräumt. Kann man davon ausgehen, oder gibt es noch weitere Möglichkeiten?
Hallo Mallett,
dass muss es nicht automatisch heißen. Vielleicht ist das ja sogar (aus irgendwelchen Gründen so gewünscht).
Diese Komponente kann ja im Hintergrund Threads starten oder weitere DLL´s nachladen.
Falls es eine Beschreibung dazu gibt, wird dort sicherlich drinstehen, wie man das Objekt korrekt Disposed (Erwarte ich jetzt einfach mal von einem Hersteller wie Siemens). Je nach dem welche Komponente das ist, kann es ja sogar immens wichtig sein, bestimmte Reihenfolgen beim Beenden einzuhalten.
Man erinnere sich an die iranische Zentrifugensteuerung in der Urananreicherungsanlage. Die sind nicht korrekt runtergefahren 😉
Das Problem daran ist halt, dass es nie beendet wird. Wenn es noch eine Zeit lang X irgendwas macht, bevor es verschwindet, das wäre ja ok. Aber es bleibt eben permanent lebendig. Wird das Ganze später ein zweites Mal geöffnet, hat man schon zwei Prozesse usw.
Siemens hat laut Kunde vorgeschlagen, einfach die .NET.exe zu beenden - das will der Kunde aber gerade nicht. Daher die Anforderung, externen Prozess aufräumen, wenn nicht mehr benötigt.
Ich könnte jetzt noch vorschlagen, das Dingen einfach per Process-Klasse zu killen, aber so richtig toll scheint mir das auch nicht zu sein.
Wie in der Beschreibung von FinalReleaseComObject zu entnehmen garantiert diese Methode nicht die Ressourcenfreigabe.
Beim Aufruf von FinalReleaseComObject wird einzig und allein dem Betriebssystem mitgeteilt, dass .NET dieses Objekt aktuell nicht mehr braucht (Reference-Counter wird auf 0 gesetzt). Wann das Objekt tatsächlich abgeräumt wird, das entscheidet das OS selbst; spätestens jedoch beim Beenden des Main-Threads.
Wenn es jedoch nie freigegeben wird, dann deutet das i.d.R. auf ein Leak hin.
Les Dir dazu auch Proper Way of Releasing COM Objects in .NET durch.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
was für eine komponente von siemens wollt ihr den da verwenden? vielleicht gibts noch einen anderen weg?
cSharp Projekte : https://github.com/jogibear9988
Hallo Mallett,
Wenn eine simple Instanzierung und anschliessende zerstörung nicht dazu führt das der Prozess sich nicht wieder beendet ist das entweder ein Fehler vom Dritthersteller oder absichtlich so gewollt. Was passiert denn wenn du den Test sofort wiederholst? Wird dann ein neuer Prozess aufgemacht? Wenn ja, liegt nach Lage der Dinge ein Fehler vor, ansonsten ist es ein beabsichtiges Verhalten.
Hallo,
sorry für die späte Antwort.
Ja, wenn ich ständig das Objekt initialisiere und dann wieder frei gebe, wird jedes Mal ein neuer Prozess auf gemacht. Deswegen gehe ich auch mal davon aus, dass die Release Logik in der Komponente entweder garnicht vorhanden oder fehlerhaft ist.
Der Hersteller der Komponente hat auf Nachfrage wie gesagt auch empfohlen, den Prozess über ProcessInfo zu beenden, das deutet eigentlich in dieselbe Richtung.
Trotzdem Danke für die Antworten.
Hallo Mallett,
Der Hersteller der Komponente hat auf Nachfrage wie gesagt auch empfohlen, den Prozess über ProcessInfo zu beenden
möglicherweise würde es reichen, die COM-Komponente in eine eigene AppDomain zu packen und diese zu entladen.
herbivore