AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign FMX-TBitmap: Nach Gebrauch von Canvas ins threads unbrauchbar?
Thema durchsuchen
Ansicht
Themen-Optionen

FMX-TBitmap: Nach Gebrauch von Canvas ins threads unbrauchbar?

Ein Thema von Renate Schaaf · begonnen am 1. Nov 2020 · letzter Beitrag vom 11. Nov 2020
Antwort Antwort
Renate Schaaf

Registriert seit: 25. Jun 2020
Ort: Lippe
114 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: FMX-TBitmap: Nach Gebrauch von Canvas ins threads unbrauchbar?

  Alt 3. Nov 2020, 19:35
Zitat:
... freizugeben...
Danke, merk ich mir
Renate
  Mit Zitat antworten Zitat
Renate Schaaf

Registriert seit: 25. Jun 2020
Ort: Lippe
114 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: FMX-TBitmap: Nach Gebrauch von Canvas ins threads unbrauchbar?

  Alt 9. Nov 2020, 11:08
Der Vollständigkeit halber hier die Version, die bei mir bis jetzt verlässlich läuft:

Meine pointer-version der Rotation hat zu dem Problem beigetragen, wieso verstehe ich im Moment nicht, aber das ist ein andere Frage.

Delphi-Quellcode:
var
  Form2: TForm2;

implementation

{$R *.fmx}

uses System.threading, System.UIConsts;

// Ohne pointers ist es sicherer
procedure Rotate(const bm: TBitmap);
var
  x, y, b, h: integer;
  DataSource, DataTarget: TBitmapData;
  help: TBitmap;
begin
  b := bm.height;
  h := bm.width;
  help := TBitmap.Create;
  try
    help.SetSize(b, h);
    Assert(bm.Map(TMapAccess.ReadWrite, DataSource));
    Assert(help.Map(TMapAccess.ReadWrite, DataTarget));
    for y := 0 to h - 1 do
    begin
      for x := 0 to b - 1 do
      begin
        DataTarget.SetPixel(x, y, DataSource.GetPixel(y, b - 1 - x));
      end;
    end;
    help.Unmap(DataTarget);
    bm.Unmap(DataSource);
    bm.Assign(help);
  finally
    help.free;
  end;
end;

procedure TextOnBitmapSimple(const bm: TBitmap; const text: String;
  cb, ct: Cardinal);
begin
  bm.Canvas.BeginScene;
  bm.Canvas.Clear(cb);
  bm.Canvas.Font.Size := 30;
  bm.Canvas.Fill.Color := ct;
  bm.Canvas.FillText(RectF(0, 0, bm.width, bm.height), text, False, 1, [],
    TTextAlign.Center, TTextAlign.Center);
  bm.Canvas.EndScene;
end;

// Ohne die mit // ? markierten Stellen geht der Canvas-Inhalt unter Android verloren
procedure TextOnBitmap(const bm: TBitmap; const text: String; cb, ct: Cardinal);
var
  am: TBitmap;
begin
  // ?Im Haupt-Thread ausführen
  TThread.Synchronize(TThread.Current,
    procedure
    begin
      // ?Den Canvas von einer temporären Bitmap benutzen
      am := TBitmap.Create;
      try
        am.SetSize(bm.width, bm.height);
        TextOnBitmapSimple(am, text, cb, ct);
        // ?Pixel rüberkopieren
        bm.CopyFromBitmap(am);
      finally
        am.free;
      end;
    end);
end;

// Gucken was los ist
procedure TForm2.ShowProgress(i: integer; const bm: TBitmap);
begin
  TThread.Synchronize(TThread.Current,
    procedure
    begin
      ProgressBar1.Value := i;
      ImageControl2.Bitmap := bm;
      // refcount ist immer 3, wieso?
      Label2.text := IntToStr(bm.Image.refcount);
      sleep(500);
    end);
end;

procedure TForm2.Button5Click(Sender: TObject);
var
  bm: TBitmap;
  i, count: integer;
  aThread: TThread;
begin
  ImageControl2.Bitmap := nil;
  aThread := TThread.CreateAnonymousThread(
    procedure
    begin
      count := trunc(SpinCount.Value);
      bm := TBitmap.Create;
      bm.SetSize(600, 400);
      TextOnBitmap(bm, 'This works', claYellow, claBlue);
      i := 0;
      while i < count do
      begin
        ShowProgress(i, bm);
        Rotate(bm);
        inc(i);
      end;
      ShowProgress(count, bm);
      bm.free;
    end);
  aThread.Start;
end;
Renate
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.479 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: FMX-TBitmap: Nach Gebrauch von Canvas ins threads unbrauchbar?

  Alt 10. Nov 2020, 22:15
Ich hatte Dein ursprüngliches Beispiel mal getestet und kann insofern die Probleme (insbesondere unter Android) bestätigen. Hatte auch festgestellt, dass die Pointer-Drehvariante eher Probleme erzeugt, als die simple Version. Ich hatte dann noch versucht es ein wenig zu optimieren (z.B. potentielle Kollisionen mit entsprechendem Auslassen von Zugriffen auf das Bitmap zu vermeiden, indem ich auf versucht habe, auf entsprechende Rückgaben von Beginsceene oder Map zu reagieren (die liefern ja ein Boolean zurück, ob ein Zugriff möglich ist oder nicht). Auch hatte ich statt Synchronize "Queue" bzw. "ForceQueue" verwendet, um den Eintritt in den Hauptthread ein wenig nach hinten zu verzögern. Ich hatte damit zwar eine "Erfolgsquote" von ca. 60-80% unter Android aber eben nicht 100% und ich konnte nicht wirklich irgendwelche Kollisionen registrieren.

Ich habe leider keine Ahnung wo das Problem genau liegt.
Mit Delhi 10.2 kam ja die Information, dass TBitmap, TCanvas und Tcontext 3D threadsicher gemacht worden seien man aber die Zugriffsweise auf diese Ressourcen etwas ändern sollte (hatte ich in meinem Buch für den Zugriff auf TCanvas beschrieben). Die Erläuterung war, dass die Zugriffe intern serialisiert werden und in eine Warteschlange kommen.

Wenn ich mir den Code in FMX.Graphics und FMX.Canvas.D2D etc. so ansehe (was sehr schwierig ist, da die entscheidenen Prozeduren virtuelle Prozeduren sind und je nach Plattform oft andere Units aufgerufen werden, man kommt also an den tatsächlichen Ablauf nur ran, wenn man debugt, was aber in einem System, das Event- und Messagebasiert arbeitet auch nicht immer möglich ist), habe ich aber den Eindruck, als ob ein Schutz nur gegeben ist, für mehrere Zugriffe auf TCanvas (Beginscene) oder TBitmap (Content) per Map aber der Mix dererlei Zugriffe eben nicht. Aber das ist eher eine Vermutung, als dass ich es wirklich beweisen könnte.

Diese Erklärung könnte aber durchaus mit Deiner Lösung zusammenpassen, da Du ja eine temporäre Bitmap erzeugst und deren Canvas manipulierst und dann den ganzen Content in die eigentliche Bitmap rüberkopierst. Und in CopyBitmap wird auch TMonitor verwendet, was auch in Map verwendet wird, so scheint also die Resource bei diesem Verfahren insgesamt schützbar zu sein.

Geändert von Harry Stahl (10. Nov 2020 um 22:25 Uhr)
  Mit Zitat antworten Zitat
Renate Schaaf

Registriert seit: 25. Jun 2020
Ort: Lippe
114 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: FMX-TBitmap: Nach Gebrauch von Canvas ins threads unbrauchbar?

  Alt 11. Nov 2020, 01:25
Vielen Dank fürs Feedback (gut, dass ich doch nicht spinne und die Erklärung dafür, dass meine Reparatur funktioniert, leuchtet mir ein, also BeginScene und Map möglichst getrennt halten.
Hast du auch eine Erklärung dafür, dass die Pointer-Version nicht funktioniert? Ich wollte eigentlich meine ganze Grafik-Bibliothek auf fmx-TBitmap umschreiben, aber wenn der Pointer-Ansatz nicht geht, kann ich die Resampler und Animationen vergessen, schade.

Ich habe noch größere Schwierigkeiten als du, den source-code zu verstehen, vor allem, wenn immer noch die styles dareinfunken..

Das Android-Betriebssystem ist mir auch erstmal ein Rätsel, vielleicht sollte ich mal in dein Buch gucken.

Danke nochmal,

Renate
Renate
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.855 Beiträge
 
Delphi 12 Athens
 
#5

AW: FMX-TBitmap: Nach Gebrauch von Canvas ins threads unbrauchbar?

  Alt 11. Nov 2020, 18:07
Könntest du mich schlafen?
Zu FMX gibt's jetzt endlich Andrea Magnani's Buch.
Bin aber noch nicht wirklich zum Lesen gekommen...
  Mit Zitat antworten Zitat
Renate Schaaf

Registriert seit: 25. Jun 2020
Ort: Lippe
114 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: FMX-TBitmap: Nach Gebrauch von Canvas ins threads unbrauchbar?

  Alt 11. Nov 2020, 20:46
@Turbomagic Fmx raubt mir den Schlaf, alles deine Schuld!

Habe das Buch und auch Harrys gekauft, mal sehen, ob ich noch was dazulernen kann.
Renate
  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 11:26 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