Ich muss hier nochmal nachfragen, weil ich die Interface-Geschichte noch nicht ganz verstanden habe, glaube ich.
Die Funktion aus dem letzten Posting (eigentlich eine private Methode einer großen Klasse, von der im Programm genau eine Instanz existiert) rufe ich mal aus einem Nebenthread auf, und mal aus dem
VCL-Thread. Dabei nutze ich nicht TThread, sondern BeginThread, woraus dann die threaded Methoden aus der großen Klasse aufgerufen werden.
Um nicht jedesmal die Factory neu zu erstellen, habe ich dafür zwei private Member-Variablen in der Klasse
Delphi-Quellcode:
WICImagingFactory_VCL: IWICImagingFactory;
WICImagingFactory_ScanThread: IWICImagingFactory;
Mit
IWICImagingFactory = interface(IUnknown)
aus der
Unit Winapi.Wincodec.
Aufgerufen wird die Methode dann über
ScalePicStreamToFile(aStream, aFilenname, 240, 240, GetProperImagingFactory(ScanMode))
Scanmode ist ein Aufzählungstyp und steuert "
VCL oder Thread". Die Factory bekomme ich dann mit dieser privaten Methode, die bei Bedarf die Factory erstellt, und ansonsten die bestehende zurückliefert.
Delphi-Quellcode:
function TMyClass.GetProperImagingFactory(ScanMode: CoverScanThreadMode): IWICImagingFactory;
begin
case ScanMode of
tm_VCL: begin
if WICImagingFactory_VCL = Nil then
CoCreateInstance(CLSID_WICImagingFactory, nil, CLSCTX_INPROC_SERVER or
CLSCTX_LOCAL_SERVER, IUnknown, WICImagingFactory_VCL);
result := WICImagingFactory_VCL;
end;
tm_Thread: begin
if WICImagingFactory_ScanThread = Nil then
CoCreateInstance(CLSID_WICImagingFactory, nil, CLSCTX_INPROC_SERVER or
CLSCTX_LOCAL_SERVER, IUnknown, WICImagingFactory_ScanThread);
result := WICImagingFactory_ScanThread;
end;
end;
end;
Jetzt habe ich beim Thread das Problem, dass nach Ende des Threads die Factory nutzlos wird (sie muss wohl immer im Kontext des Threads erstellt werden, in dem sie genutzt wird). Daher muss ich die freigeben, und die Variable auf Nil setzen, damit beim nächsten Thread (es läuft aber immer nur einer nebenbei) wieder eine neue erstellt wird.
Das habe ich so gemacht
Delphi-Quellcode:
WICImagingFactory_ScanThread._Release
WICImagingFactory_ScanThread := Nil
Bei mir läuft das, bei vielen anderen knallt die Zuweisung auf Nil. So grob habe ich auch schon verstanden, warum: Wenn durch das Release der Referenzzähler Null wird, wird das Objekt dahinter freigegeben. Die Zuweisung auf Nil hingegen ruft intern wieder Release auf, aber das Objekt ist schon weg.
In der
VCL-Komponente TWICImage ist diese Factory eine Class Var. Wenn ich den Code aus TWICImage.Destroy übernehme, komme ich auf
Delphi-Quellcode:
if WICImagingFactory_ScanThread._Release = 0 then
Pointer(WICImagingFactory_ScanThread) := Nil;
Das funktioniert dann. Sehe ich das richtig, dass durch den Cast auf Pointer einfach nur die Variable auf NIL gesetzt wird, und die "Interface-Magic" dahinter nicht aktiviert wird, und somit das erreicht wird, was ich haben will? Nämlich dass das Objekt weg ist, und die Variable Nil ist?
Oder ist der ganze Ansatz kompletter Murks?
The angels have the phone box.