Einzelnen Beitrag anzeigen

Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#20

AW: Programm mit Zugriffsverletzung - 1. PC funktioniert - 2. Nicht

  Alt 13. Apr 2014, 17:35
Ich habe im QC noch einiges ergänzt. Ich habe herausgefunden, dass es tatsächlich an den Threads liegen muss. Wenn ich einfach nur ein Sleep(500) vor das Load setze, brauche ich keine OLE Initialisierung. Auch auf einem älteren PC läuft es manchmal beim ersten Versuch bevor der Cache zuschlägt.

Mit dem Sleep kommen auch keinerlei Bildfehler mehr und es ging in allen Versuchen auf allen PCs.
Generell liegt es wohl daran, dass FMX-Framework erst komplett initialisiert sein muss, damit der Code funktioniert.
Mit einem Thread kommt es bei diesem Verhalten auf das Timing an. Ist die Framework-Initialisierung abgeschlossen bevor der Thread startet, dann ist alles gut, ansonsten kommt ein Fehler im ImageDataSoure bei TBitmap.CreateFromFile bzw. (mit Debug-DCUs)
Delphi-Quellcode:
function TBitmapCodecWIC.LoadFromFile(const AFileName: string;
  const Bitmap: TBitmapSurface): Boolean;
...
begin
  ...
  try
    TCanvasD2D.ImagingFactory.CreateDecoderFromStream(SA, GUID_NULL, WICDecodeMetadataCacheOnDemand, dec); // <- hier
    ...
  finally
    FS.Free;
  end;
end;
Wenn man jetzt (nur so zum Spass) einen Timer auf die Form klatscht, mit einem Interval von 1 und in diesem Timer, dann den Thread startet (anstatt im FormCreate):
Delphi-Quellcode:
procedure TFormMain.StartupTimerTimer(Sender: TObject);
begin
  StartupTimer.Enabled := False;
  // Start loading
  FSplashImageLoader.Start;
end;
dann gibt es auch keine Zugriffsverletzungen und die Bilder werden korrekt angezeigt.

Die Load-Methode habe ich auch etwas angepasst, damit bei einem Fehler nicht die ganze Hütte zusammenbricht
statt
Delphi-Quellcode:
      SetLength( FImages, I + 1 );
      FImages[I] := TBitmap.CreateFromFile( ImagesPath + SR.Name );
nehmen wir
Delphi-Quellcode:
      LBitmap := TBitmap.CreateFromFile( ImagesPath + SR.Name );
      SetLength( FImages, I + 1 );
      FImages[I] := LBitmap;
Manchmal muss man nur geschickter und sorgfältiger arbeiten und das Wesen des Frameworks verstehen (nicht wahr, E***a)

Den komplett geänderten Source habe ich mal angehängt zum Testen
Angehängte Dateien
Dateityp: zip MetropolisUIFlipViewDemo.zip (174,7 KB, 3x aufgerufen)
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (13. Apr 2014 um 17:37 Uhr)
  Mit Zitat antworten Zitat