AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

OCX wird nicht freigegeben

Ein Thema von Evil MM · begonnen am 29. Okt 2007 · letzter Beitrag vom 7. Nov 2007
Antwort Antwort
Evil MM

Registriert seit: 29. Okt 2007
4 Beiträge
 
#1

OCX wird nicht freigegeben

  Alt 29. Okt 2007, 16:53
Hallo zusammen!
Ich habe ein großes Problem, zu dem ich noch keine Lösung gefunden habe.

Ich habe unter Delphi eine OCX-Komponente geschrieben. Diese Komponente hat eine ActiveForm.
Aus dieser Komponente erzeuge ich nun ein Objekt und gebe es anschließend wieder frei.

Normalerweise müsste ja jetzt auch die OCX wieder freigegeben sein, aber das ist sie nicht - sie ist immer noch gesperrt und offenbar scheint irgendeine Referenz auf die OCX zu zeigen.

Meine Frage: wie kann ich erzwingen, dass die OCX-Komponente nach der Zerstörung aller Objekte daraus wieder korrekt freigegeben wird?

Andere OCX-Komponenten (in C++ geschrieben) werden bei gleichem Aufruf wieder freigegeben.
Zudem passiert das auch, wenn ich ein ganz frisches Projekt erzeuge.

Also: ActiveX-Projekt und anschließend Datei/Neu und ActiveForm. Kompilieren, testen, geht nicht

Um Hilfe wäre ich sehr Dankbar!

Grüße und Danke im Voraus
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#2

Re: OCX wird nicht freigegeben

  Alt 29. Okt 2007, 17:06
Zitat von Evil MM:
Normalerweise müsste ja jetzt auch die OCX wieder freigegeben sein, aber das ist sie nicht - sie ist immer noch gesperrt und offenbar scheint irgendeine Referenz auf die OCX zu zeigen.
Das wird wohl das Problem sein.
Die Anzahl der offenen Referenzen lässt sich über
ComServer.ObjectCount ermitteln.
Die globale Variable ComServer muss dazu natürlich von der OCX heraus benützt werden.
Du solltest auch mal einen Eventhandler für COMServer.OnLastRelease bereitstellen,
um genau festzustellen, wann die letzte Referenz "flöten gegangen" ist.

Delphi-Quellcode:
THelper = class(TObject)
  procedure OnLastReleaseHandler(Sender:TObject);
end;
procedure THelper.OnLastReleaseHandler(Sender:TObject);
begin
  ShowMessage('letzte Referenz ist nun weg');
  // ggf. OutputDebugString anstelle von ShowMessage verwenden
end;

var
  gHelper : THelper;

initialization
  gHelper := THelper.Create;
  COMServer.OnLastRelease := gHelper.OnLastReleaseHandler;
finalization
  COMServer.OnLastRelease := nil; // Zur Sicherheit
  gHelper.free;


Zitat von Evil MM:
Meine Frage: wie kann ich erzwingen, dass die OCX-Komponente nach der Zerstörung aller Objekte daraus wieder korrekt freigegeben wird?
Das würde ich nun überhaupt nicht empfehlen. Daraus folgen nur schwerwiegende Probleme beim Programmende.
Andreas
  Mit Zitat antworten Zitat
Evil MM

Registriert seit: 29. Okt 2007
4 Beiträge
 
#3

Re: OCX wird nicht freigegeben

  Alt 30. Okt 2007, 10:54
Hallo,
erstmal vielen Dank für die schnelle Antwort. Ich habe nun in alle Destroy-Blöcken die es gibt den Wert ComServer.ObjectCount ausgewertet. Tatsächlich steht er in einem Destroy-Block (der letzte der aufgerufen wird) auch auf 0. Jedoch bleibt die OCX wohl noch geladen.

Ich habe nun gedacht, das ich einfach eine Abfrage einbaue die so aussieht:

if ( ComServer.ObjectCount = 0 ) then CoFreeUnusedLibraries; Aber dann wird das ganze Programm, dass die OCX verwendet, gleich mitbeendet.

"Schieße" ich die OCX ab, wenn der Counter auf 0 steht (immerhin braucht dann wohl keine Anwendung mehr die OCX) und zwar durch diesen Aufruf im Destroy:

if ( ComServer.ObjectCount = 0 ) then ComServer.Free; Dann verhält es sich so wie es soll, also:

1. Die Anwendung wird gestartet
2. Ein Objekt aus der OCX wird erzeugt
3. Das Objekt wird freigegeben
4. OCX ist freigegeben.

Das klappt tausendmal hintereinander (Objekterzeugung und freigabe) bis die Anwendung selbst beendet wird. Dann gibt es einen Ausnahmefehler von wegen InvalidPointer.
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#4

Re: OCX wird nicht freigegeben

  Alt 30. Okt 2007, 11:33
Zitat von Evil MM:
Ich habe nun in alle Destroy-Blöcken die es gibt den Wert ComServer.ObjectCount ausgewertet. Tatsächlich steht er in einem Destroy-Block (der letzte der aufgerufen wird) auch auf 0. Jedoch bleibt die OCX wohl noch geladen.
Das ist höchstwahrscheinlich ein gewünschtes Verhalten seitens des Betriebssystems.
Angenommen, in der OCX gibt es eine CoClass und dein Programm erzeugt ein Objekt und zerstört es gleich wieder.
Dann würde jedesmal die OCX geladen und wieder entladen werden. => grosser Performanceverlust
Intelligenter wäre da ein verzögertes Entladen (delayed unload) nach 2 bis 3 Minuten.
Und das wird IMHO unter Windows auch so gemacht.

Bei Delphi könnte es noch einen anderen Grund geben:
Delphi-Quellcode:
function DllCanUnloadNow: HResult;
begin
  if (ComServer = nil) or
    ((ComServer.FObjectCount = 0) and (ComServer.FFactoryCount = 0)) then
    Result := S_OK
  else
    Result := S_FALSE;
end;
Man sieht, die OCX wird nur entladen wenn sowohl ObjectCount als auch FactoryCount gleich 0 ist.
Da aber FactoryCount normalerweise nicht 0 wird, bleibt die OCX geladen.
Du könntest nun deine eigene Funktion schreiben und exportieren:
Delphi-Quellcode:
library Project1;
uses
  ComServ;
exports
  DllGetClassObject,
  DllCanUnloadNow,
  DllRegisterServer,
  DllUnregisterServer;

function DllCanUnloadNow: HResult;
begin
  if (ComServer = nil) or
    ((ComServer.FObjectCount = 0) {and (ComServer.FFactoryCount = 0))} then
    Result := S_OK
  else
    Result := S_FALSE;
end;
Andreas
  Mit Zitat antworten Zitat
Evil MM

Registriert seit: 29. Okt 2007
4 Beiträge
 
#5

Re: OCX wird nicht freigegeben

  Alt 7. Nov 2007, 15:50
Das Problem scheint sich für uns gelöst zu haben. Ich werds hier aber der Vollständigkeit halber beschreiben:

Die OCX wurde - auch mehrmals gleichzeitig - verwendet und somit wurde parallel Objekte daraus erzeugt.

1. Fehler: nicht alle Objekte wurden bereinigt. Also peinlichst genau darauf achten, dass die Destroy-Methoden durchlaufen werden. Ggf. überschreiben und dort erzeugte Objekte freigeben.
2. ThreadingModell: mit tmApartment gabs Probleme. Überall tmBoth benutzen, damit die OCX ThreadSafe ist.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:13 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz