AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Threads und TBitmaps

Ein Thema von TheGroudonx · begonnen am 12. Aug 2014 · letzter Beitrag vom 10. Okt 2017
Antwort Antwort
Seite 1 von 8  1 23     Letzte » 
TheGroudonx

Registriert seit: 21. Mai 2014
42 Beiträge
 
#1

Threads und TBitmaps

  Alt 12. Aug 2014, 12:37
Hallo,

ich möchte ein Program so abändern, dass CPU-lastige Grafikfunktionen von einem anderen Kern, also in einem Thread, abgearbeitet werden.
Dabei soll in einem bestimmtem Interval das berechnete Bild(TBitmap) auf die Mainform(TImage) kopiert werden.
Ich habe bis jetzt folgende Ansätze ausprobiert:
1. Das Bild wird von dem Thread auf die Mainform gezeichnet.
2. Die Mainform zeichnet das Bild durch Nachfrage an den Thread selbst.

Das funkioniert kurzzeitig auch relativ gut, nur gibt es eben danach je nach Ansatz EOutofresource-Fehler(1) oder ein leeres Ergebnisbild(2), quasi zu einem zufälligen Zeitpunkt...
Der EOutofresource-Fehler heißt meistens "Falscher Parameter".

Der untere Quelltext ist ein einfaches Beispiel für die Basisfunktionen, die bei meinem Program gebraucht werden.
Er erzeugt nach z.B. 1 Min die Fehlermeldung.



procedure TPaintThread.Execute;
begin

while (Terminated = False) do
begin

if (MyBild = NIL) then
begin

randomize;

MyBild := TBitmap.create;
MyBild.Width := 1000;
MyBild.Height := 1000;
MyBild.Canvas.Brush.Color := clgreen;

end
else
begin

MyBild.Canvas.Rectangle(0, 0, random(500) + 1, random(500) + 1);
Form1.Image1.Picture.Bitmap := MyBild; //Ansatz 1

end;

sleep(1);

end;
end;


Meine Frage ist nun, wie sich Zeichenoperationen auslagern lassen, ohne Fehlermeldungen auszulösen.
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#2

AW: Threads und TBitmaps

  Alt 12. Aug 2014, 13:37
Zunächst einmal darfst Du aus einem Thread heraus nicht auf den Canvas malen, also VCL-Operationen ausführen. Ergo kann dein Thread die Bitmaps nur neu berechnen. Zeichnen muss der Hauptthread

Du könntest einen Timer im Hauptthread starten, der alle 20ms Sekunden die Bitmap neu zeichnet (wenn sie sich verändert hat). Die Threads verändern nun irgendwann, von mir auch aus öfter als alle 20ms, das Bitmap und legen den Schalter 'Bitmap hat sich geändert' um.

Der Hauptthread fragt den Schalter alle 20ms ab und zeichnet dann neu.

Schalter und Bitmap müssen über Resourcenschutzblöcke (einer reicht) (TCriticalSection) gesichert werden.
  Mit Zitat antworten Zitat
Benutzerbild von bernau
bernau
Online

Registriert seit: 1. Dez 2004
Ort: Köln
999 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#3

AW: Threads und TBitmaps

  Alt 12. Aug 2014, 14:00
Die Ressourcen dürften bei dir schwinden, weil du ein Bitmap erzeugst (mit Create) aber am Ende der Procedure nicht frei gibst (Free). Das Bitmap hat mit den Dimensionen eine größe von 3MB. kannst ja ausrechnen, wie oft man ein Bitmap erzeugen kann, bis der Hauptspeicher aufgebraucht ist.
Gerd
Kölner Delphi Usergroup: http://wiki.delphitreff.de
  Mit Zitat antworten Zitat
Benutzerbild von bernau
bernau
Online

Registriert seit: 1. Dez 2004
Ort: Köln
999 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#4

AW: Threads und TBitmaps

  Alt 12. Aug 2014, 14:03
Sehe grade, daß du MyBild auf NIL testest. Mein Post hat sich also erledigt.
Gerd
Kölner Delphi Usergroup: http://wiki.delphitreff.de
  Mit Zitat antworten Zitat
Whookie

Registriert seit: 3. Mai 2006
Ort: Graz
410 Beiträge
 
Delphi 10.3 Rio
 
#5

AW: Threads und TBitmaps

  Alt 12. Aug 2014, 14:21
Wenn es nur darum geht nach einem längerem Zeichenprozess das Bild in der MainForm darzustellen könnte man das auch so machen:

Delphi-Quellcode:
constructor TImageRenderer.Create;
begin
  inherited Create;
  fBmp := TBitmap.Create;
  fBmp.SetSize(100, 100);
  fBmp.PixelFormat := pf24Bit;
end;

destructor TImageRenderer.Destroy;
begin
  fBmp.Free;
  inherited;
end;

procedure TImageRenderer.Execute;
var
  ix: Integer;
  iy: Integer;
begin
  while Not Terminated do
  begin
    fBmp.Canvas.Lock;
    for ix := 0 to 99 do
    begin
      for iy := 0 to 99 do
      begin
        fBmp.Canvas.Pixels[ix,iy] := RGB(Random(256),Random(256),Random(256));
      end;
      Sleep(5);
    end;
    fBmp.Canvas.UnLock;
    Synchronize(PaintBmp);
  end;
end;


procedure TImageRenderer.PaintBmp;
begin
  if assigned(fOnPaint) then
  begin
    fOnPaint(fBmp);
  end;
end;
Angehängt ist ein kleines Projekt mit dem das läuft...
Angehängte Dateien
Dateityp: 7z ThreadImgCopy.7z (4,0 KB, 15x aufgerufen)
Whookie

Software isn't released ... it is allowed to escape!
  Mit Zitat antworten Zitat
TheGroudonx

Registriert seit: 21. Mai 2014
42 Beiträge
 
#6

AW: Threads und TBitmaps

  Alt 12. Aug 2014, 15:53
Hallo Whookie,

ich hab mir dein Projekt mal angesehen und es an Delphi 7 angepasst,
starte ich es und drücke den Button so wird jedoch sofort eine Fehlermeldung(s. Anhang) ausgegeben :/
Miniaturansicht angehängter Grafiken
program.jpg  
  Mit Zitat antworten Zitat
Whookie

Registriert seit: 3. Mai 2006
Ort: Graz
410 Beiträge
 
Delphi 10.3 Rio
 
#7

AW: Threads und TBitmaps

  Alt 12. Aug 2014, 18:31
Ups ... Delphi 7 ... soweit ich weiß hat sich gerade in den Thread-Klassen einiges getan....
was hier das Problem ist, kann ich so leider nicht sagen...

Ich würde dir empfehlen das ganze mal auszubauen und zu sehen wo das Problem liegt:

Delphi-Quellcode:
procedure TImageRenderer.Execute;
var
  ix: Integer;
  iy: Integer;
begin
  while Not Terminated do
  begin
    for ix := 0 to 99 do
    begin
      for iy := 0 to 99 do
      begin
      end;
      Sleep(5);
    end;
    Synchronize(PaintBmp);
  end;
end;
sollte mal laufen (aber erst mal ohne OnPaint zu verbinden)
Whookie

Software isn't released ... it is allowed to escape!
  Mit Zitat antworten Zitat
TheGroudonx

Registriert seit: 21. Mai 2014
42 Beiträge
 
#8

AW: Threads und TBitmaps

  Alt 30. Aug 2014, 23:59
Tut mir Leid für die lange Zeitspanne bis zur Antwort,

ich habe mittlerweile herausgefunden, dass der Aufruf aus dem Thread heraus das Problem ist.
Er soll auf der Form das Bild zeichnen, was zu dem Fehler führt.
Wird im Thread jedoch nur die Berechnung der Threadeigenen Bitmap durchgeführt und diese durch die Form per Canvas.draw kopiert, so funktioniert es fehlerfrei. Zwar erzeugt das wiederum Auslastung, welche eigentlich im Thread sein sollte, jedoch scheint es sich nicht vermeiden zu lassen.

Edit: Die Threadeigene Bitmap muss im Canvas unlocked werden, damit das Bild auf der Form nicht einfriert

Geändert von TheGroudonx (31. Aug 2014 um 00:01 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Chemiker
Chemiker

Registriert seit: 14. Aug 2005
1.787 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#9

AW: Threads und TBitmaps

  Alt 31. Aug 2014, 10:18
Hallo TheGroudonx,

man sollte auf jeden Fall den Canvas.lock und Canvas.unlock in einem Schutzblock fassen um die Ausgabe wieder freizugeben, die exklusiv für den Thread geblockt worden ist.
Bei der Ausgabe sollte man bedenken, dass die Grafikausgabe vom BS gepuffert wird, dass bedeutet das wenn der Thread vor der Ausgabe schlafen gelegt wird, keine Ausgabe erfolgt. Mit der Function GdiFlush() kann die Ausgabe erzwungen werden.

Bis bald
Chemiker
wer gesund ist hat 1000 wünsche wer krank ist nur einen.
  Mit Zitat antworten Zitat
TheGroudonx

Registriert seit: 21. Mai 2014
42 Beiträge
 
#10

AW: Threads und TBitmaps

  Alt 1. Sep 2014, 11:42
Hallo,

ich verzweifle so langsam an dem Thema Threads...
zwar wird ein Bild ausgegeben, aber es gibt so viele mehr oder weniger zufällig auftretende Fehler...

-Zuerst einmal funktioniert das Schritt-für-Schritt kompilieren des Threads nicht wirklich:
Ein normal durchlaufender Thread bricht beim Schritt-für-Schritt durchgehen zufällig nach ung. 20 durchgängen ab und ist nichtmehr startbar, oder er gibt access violation messages wieder, die sonst nicht kämen, obwohl die Elemente existieren müssten.

-Versuche ich eine Bitmap in ihrer Größe zu verändern, so kommt es dadurch zu einer EOutofrecource-Fehlermeldung. Selbst wenn man die Bitmap auf ihre eigene Größe anpasst, also keine Veränderung, geht das komplette Bild verloren - Was passiert denn da im Thread? Erzeugt er etwa jedesmal eine neue Bitmap, wenn man die Größe ändert, und müllt den Speicher mit den alten Kopien voll?

-Letztendlich ist das Unlocken für mich noch relativ unklar...muss eine Bitmap bei jedem Zeichnen/Prozeduraufruf neu unlocked werden? Ein Projekt von mir Brach ab, obwohl nach dem Create alle Bitmaps unlocked wurden. Der Fehler lies sich nach Debuggen beheben, indem der unlockbefehl einer Bitmap nach create DOPPELT, also HINTEREINANDER!!!, geschrieben wurde.

Das ganze Thema Threads scheint durch und durch voller Fehler zu stecken, es macht kaum Spaß sich den Weg aus denselben zu bahnen...
Jedenfalls in meiner Delphi 7 Version.

Wenn ihr Tipps zu den geschilderten Ereignissen habt die etwas Licht ins Dunkle bringen lasst es mich wissen.
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 20:19 Uhr.
Powered by vBulletin® Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2019 by Daniel R. Wolf