Einzelnen Beitrag anzeigen

Benutzerbild von Harry Stahl
Harry Stahl

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

AW: Multithreaded Zeichnen

  Alt 3. Jul 2018, 00:54
Ich versuche die Zeit zu verkürzen, die meine Applikation einfriert, wenn ich zeichne. Da ab Tokyo Bitmaps threadsicher sein sollen, habe ich das zeichnen auf die Bitmap in einen Thread ausgelagert und möchte die fertige Bitmap per Synchonize an die GUI übergeben.

Im Ergebnis sollte eine Bitmap mit wildem Zickzack einmal pro Sekunde neu gezeichnet werden.

Was mache ich falsch?
Ich habe im Moment leider kein IOS-Gerät im Entwicklungs-Einsatz, kann daher meinen Vorschlag nicht selber testen, muss ich Dir also überlassen.
Deine Variante funktioniert jedenfalls auf einem Android-Device, könnte also ggflls. auch ein spezielles IOS-Problem sein.

"Threadsicher" heißt ab 10.2, dass die Zugriffe mehrerer Threads auf einen Canvas intern von Delphi serialisiert werden. Damit hat sich auch die Art, wann man ein Locking vornimmt, etwas geändert, da bei Dir aber nicht mehrere Threads an einer Grafik arbeiten und Du ja gewollt eine Pause von 1 Sekunde haben willst, ist das hier egal (mehr Infos hierzu bei Bedarf in meinem aktuellen FMX-Buch im Grafik-Kapitel unter 6.4).

Diese Änderung hat aber letztlich auch zur Konsequenz, dass Du das temporäre Bitmap gar nicht mehr brauchst, sondern direkt Image1.bitmap zum zeichnen verwenden kannst (eine extra Synchronisierung entfällt also). Damit sollte auch das Zuweisungsproblem von fBMp an Image1.bitmap entfallen, das aus irgendeinem Grund anscheinend nicht unter IOS funktioniert (wäre zwar ein "umgehen" des Problems, aber eine Lösung, die man mal versuchen könnte, ist ja nicht mehr als copy und paste):

Schlage also mal vor zu testen, ob es so auch auf Deinem IOS-Device funktioniert(unter Windows, Linux, Android geht es):

Delphi-Quellcode:
procedure TPainter.Execute;
var
  myPoint1 : TPoint;
  myPoint2 : TPoint;
  i : integer;
begin
  inherited;
  while not Terminated do
  begin
    myPoint1 := TPoint.Zero;
    if Form15.Image1.bitmap.Canvas.BeginScene then
    begin
      Form15.Image1.bitmap.Canvas.Clear(TAlphaColorRec.Null);
      Form15.Image1.bitmap.Canvas.Stroke.Thickness := 1;
      Form15.Image1.bitmap.Canvas.Stroke.Color := TAlphaColorRec.Black;
      try
        for i := 0 to 1000 do
        begin
          myPoint2 := TPoint.Create(Random(Form15.Image1.Bitmap.Width), Random(Form15.Image1.bitmap.Height));
          Form15.Image1.bitmap.Canvas.DrawLine(myPoint1, myPoint2, 1);
          myPoint1 := myPoint2;
        end;
      finally
        Form15.Image1.bitmap.Canvas.EndScene;
      end;
    end;
    //Synchronize(updateGui); // wird nicht benötigt
    Sleep(1000);
  end;
end;
Image1.bitmap muss irgendwo natürlich noch mit einer sinnvollen Größe vorbelegt werden.
Harry Stahl
  Mit Zitat antworten Zitat