2009-05-27 3 views
1

Ich verwende anonyme Methoden, um Ereignisse in einem COM-Objekt zu behandeln. Sobald das Programm beendet wird, scheint es, dass die Ressourcen, die ich in der anonymen Methode verwende, nicht "korrekt geschlossen" werden, da ich für jede Ressource, die ich gerade sah, eine Ausnahme der ersten Chance (InvalidComObjectException) erhalte. Ich nehme an, das ist keine große Sache, aber es fühlt sich nicht "richtig" an.Wie kann man erfasste Variablen in anonymen Methoden freigeben/löschen/löschen?

Ich kann einen Weg nicht verstehen, auf diese erfassten Variablen außerhalb des Bereichs der anonymen Methoden zuzugreifen (was du sowieso nicht können sollst). Wie kann ich die Ressourcen vor dem Beenden der Anwendung schließen/entsorgen?

EDIT: Nach einer kurzen Neu-Lesung, kann es nicht klar sein, was ich hier mache. Ich schreibe eine verwaltete Anwendung, die ein COM-Objekt verwendet.

Weiter Bearbeiten: Ich verwende ArcGIS Engine, um GIS-Daten zu manipulieren. In diesem speziellen Fall verwende ich das VisibilityChanged-Ereignis in ILayerEvents_Event, um zu überwachen, wann eine GIS-Schicht sichtbar oder unsichtbar gemacht wird. Das Ereignis übergibt NUR einen Bool (sichtbar oder nicht sichtbar) und NICHT den Layernamen. Daher müsste eine Methode für JEDEN Layer erstellt werden, um den Sichtbarkeitsstatus zu ändern. Da ich mich mit dynamischen Ebenen beschäftige, brauchte ich eine Möglichkeit, dies irgendwie dynamisch zu machen, daher die anonymen Methoden.

Innerhalb der Anonymousa-Methode habe ich eine ILayer-Variable, die das ILayerEvents_Event von einer äußeren Schleife (in einem ILayer-Kontext) ergreift, so dass ich weiß, mit welcher Schicht ich arbeite. Es ist an diesem Punkt, dass ich feststecke. Die Funktionalität funktioniert und alles ist großartig, bis ich die Anwendung verlasse und die 20+ Referenzen dort hängen lasse, ohne einen Platz für eine Ausnahme.

Ich habe keine Ahnung, wann der Benutzer eine Schicht zum letzten Mal verstecken/zeigen wird, also gibt es keine Möglichkeit, Dinge auf die letzte Stufe zu bringen. Ich nehme an, ich kann es einfach so lassen wie es ist (oder vielleicht gibt es einen besseren Weg dies zu tun als die anonymen Methoden), da es scheinbar nichts verletzt. Ich denke nur, dass ich etwas vermisse.

+0

Sie wissen, dass Sie das Gefühl haben, wenn Sie ununterbrochen an etwas gearbeitet haben und Sie es schließlich durchbrechen? Ich bin dort. Danke für die Hilfe von allen (einschließlich Marc Gravell aus einem separaten Post). Ich musste schließlich eine Liste der COM-Objekte und der an ihre Ereignisse angehängten anonymen Methoden führen und meldete dann die Delegierten vor dem Herunterfahren ab. Das hat Dinge funktioniert, ohne die Ausnahme zu werfen. –

Antwort

1

Es ist nicht ganz möglich, dies anhand Ihrer Beschreibung zu ermitteln. Möglicherweise verfügen Sie jedoch über ein COM-Objekt, das Verweise auf C# -Objekte enthält, da Methoden für diese Objekte als Ereignishandler für ein Ereignis eingetragen sind das COM-Objekt, und wenn das COM-Objekt nicht mehr verwendet wird, wird es abgeschlossen. Unter der Annahme, dass das COM-Objekt "Apartment" -basiert ist, bedeutet dies, dass eine Nachricht vom Finalizer-Thread an die Windows-Nachrichtenwarteschlange des Threads gesendet wird, der das COM-Objekt erstellt hat, und dass Release für das COM-Objekt aufgerufen werden soll. An diesem Punkt ruft das COM-Objekt wahrscheinlich Release für die C# -Objekte auf, die alle eingetragenen Event-Handler implementieren.Dies geschieht wahrscheinlich, wenn der letzte verwaltete Code Ihrer Anwendung ausgeführt wurde und die CLR gerade versucht, sich selbst zu entladen. Es kann sein, dass die CLR während des Herunterfahrens mit möglichen Lecks von Referenzzählungen fertig wird, indem sie erlaubt, dass Objekte gesammelt oder in einen ungültigen Zustand versetzt werden, bevor ihre Referenzzählungen auf Null gefallen sind. Also könnte dies (reine Vermutung) erklären, was Sie sehen.

Wenn dies der Fall ist, müssen Sie das COM-Objekt zu einem von Ihnen gewählten Zeitpunkt herunterfahren. Die Lösung besteht darin, Marshal.ReleaseComObject in einer Schleife aufzurufen, bis es auf dem COM-Objekt als Teil des normalen Herunterfahrens der Anwendung Null zurückgibt.

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.releasecomobject(VS.71).aspx

Update auf aktualisierte Frage zugrunde:

Okay, so dass Sie einige COM-Objekte haben durch die anonyme Methode Verschlüsse bezeichnet. Die einzige Sache, die mit diesen COM-Objekten passiert, ist, dass Release für sie aufgerufen wird. Wenn das ein Problem verursacht, ist es wahrscheinlich, dass sie sich bereits in einem ungültigen Zustand befinden.

Daher würde ich empfehlen, dass Sie diese COM-Objekte in einer separaten Liste hinzufügen, wenn Sie den Satz der anonymen Methodenabschlüsse vornehmen, die Verweise auf die COM-Objekte enthalten. Auf diese Weise können Sie dann Marshal.ReleaseComObject aufrufen, wenn Sie das gesamte System verwerfen.

1

Wenn Sie wirklich möchten, müssen Sie sich in das Application-Exit-Ereignis einklinken. Aber ich denke, es wäre schön, das besser zu machen.

Wofür verwenden Sie die anonyme Methode? Können Sie nach der letzten Verwendung trainieren und die COM-Objekte dann entsorgen? Können Sie die anonymen Methoden veranlassen, die COM-Objekte und zu entsorgen, alle im selben Block?

Wie Sie sehen können, der Teufel steckt im Detail :)

+0

Ich habe ein bisschen mehr Informationen in der Frage hinzugefügt. Jede Hilfe wäre großartig. –

2

Try unsicheren Modus in C# zu verwenden, Sachen auf dem Heap erstellen und löschen, wenn Sie fertig. Eine andere Idee besteht darin, einen Verweis auf die Ressourcen in Variablen zu speichern, die außerhalb der anonymen Methode liegen, und sie beim Beenden des Programms korrekt zu schließen. Dann brauchen Sie nur noch einen Aufruf an Dispose().

Ein wenig mehr Info wäre hilfreich. Wann wird die Ausnahme ausgelöst? Was meinst du mit Ressourcen und "richtig geschlossen".

+0

Ich habe oben ein bisschen mehr Informationen hinzugefügt. Denken Sie, dass etwas wie das Halten einer Liste <> der referenzierten Objekte und das anschließende Bearbeiten dieser Objekte in Ordnung wäre? –