Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Thread mit komischem Verhalten (https://www.delphipraxis.net/187951-thread-mit-komischem-verhalten.html)

Schwedenbitter 18. Jan 2016 23:00

Delphi-Version: XE5

Thread mit komischem Verhalten
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

ich versuche, die Kompression von Bitmaps (nach PNG bzw. JPG) in einen Thread auszulagern. Den entsprechenden Code habe ich angehängt.
Das komische daran ist, dass die Ausgabe der fertigen Dateien perfekt funktioniert, wenn ich mit
Delphi-Quellcode:
{$DEFINE DebugUnit}
bestimmten Code mit ausführen lassen. Es handelt sich dabei um eine "LOG-Datei", die mir die Dateinamen der Quelldateien ausgibt. Das ganze realisiere ich über eine
Delphi-Quellcode:
TStingList
.

Wird dieser Code nicht mit compiliert, funktioniert es plötzlich nicht mehr - also es werden keine Ausgabe-Dateien in Form von PNG bzw. JPG.

Im Moment bin ich sehr ratlos und würde mich freuen, wenn mir jemand sagen kann, woran es liegt.

Gruß, Alex

Sir Rufo 18. Jan 2016 23:31

AW: Thread mit komischem Verhalten
 
Da kann ich dir helfen:

Jedes Mal, wenn du Delphi, Bitmap und Thread in einem Satz sagst, streichst du diesen Satz (bis auf Weiteres) wieder aus deinem Gedächtnis :stupid:

Du kannst fast alles im Thread machen, aber Bitmaps (VCL/FMX) gehen nicht!

Marco Cantù
In general, bitmap operations in background threads have never been allowed, although they do occasionally work.
https://community.embarcadero.com/fo...ng-in-xe8#1984

Schwedenbitter 18. Jan 2016 23:48

AW: Thread mit komischem Verhalten [Bild-Kompression]
 
Zitat:

Zitat von Sir Rufo (Beitrag 1327416)
Du kannst fast alles im Thread machen, aber Bitmaps (VCL/FMX) gehen nicht!

Danke erstmal für die Antwort. Das nehme ich so zur Kenntnis und gräme mich! Dass ich keine Operationen auf dem Canvas machen soll, habe ich schon so gelesen und daher in mein Hauptprogramm/-thread realisiert.

Allerdings ist die Umwandlung von zig BMP in JPG und insbesondere von PNG nicht ein einem Hauptprogramm für den Benutzer erträglich machbar. Da käme mir einzig die Idee, ein weiteres kleine Programm zu schreiben, was im Hintergrund läuft und dessen Resourcen vom BS zugeteilt werden. Ich fände das aber keine schöne Lösung.
Wenn ich die Antwort sklavisch lese, gehen also "nur" VCL/FMX nicht; GDI+ evtl. dagegen schon. Letzteres ist aber so kompliziert, dass ich davon schon seit langem wieder die Finger gelassen habe.

Wie macht man es dann möglichst einfach und für Laien wie mich handhabbar?

Sir Rufo 19. Jan 2016 00:16

AW: Thread mit komischem Verhalten
 
Sehe gerade, dass du wohl ein VCL-Programm schreibst.

Dann kannst du Bitmap32 von graphics32.org nehmen. Die gehen auch im Thread ;)

Luckie 19. Jan 2016 02:19

AW: Thread mit komischem Verhalten
 
Nur um Klarheit zu bekommen. Man kann kein Bitmap-Objekt in einem Thread außer dem Hauptthread erstellen?

Medium 19. Jan 2016 02:32

AW: Thread mit komischem Verhalten
 
Bisher, bei den Dingen die ich bisher so in Threads gemacht habe, und Bitmaps waren dabei, war es eigentlich immer so, dass Ressourcen die ich in einem Thread-Kontext nutzen will, diese auch dort erzeugt werden müssen. Das heisst insbesondere bei der Delphi-RTL-Implementierung "TThread": Etwas, was im Konstruktor erzeugt wird, ist NICHT im Thread-Kontext, sonderm im Hauptthread erzeugt. Nur Dinge die in der Execute-Methode erstellt werden sind auch wirklich im Thread-Kontext, und gerade bei so manchen Systemressourcen, und insbesondere bei GDI-Zeug scheint das recht wichtig zu sein. (Ich habe mir den Code jetzt nicht angeschaut um zu wissen ob das hier zutrifft, ich sollte eigentlich schleunigst ins Bett.) Und so lange man ein Bitmap in Thread-Kontext im selben Kontext auf die Platte schreibt, und nicht etwa noch fix auf einem Formular darstellen will, muss man sich imho nichtmals um irgendwelche Synchronisierungen kümmern.
Meine Erfahrungen decken sich hier nicht mit Marcos Aussage.

Schwedenbitter 19. Jan 2016 05:35

AW: Thread mit komischem Verhalten
 
Zitat:

Zitat von Medium (Beitrag 1327422)
Bisher (...) war es eigentlich immer so, dass Ressourcen die ich in einem Thread-Kontext nutzen will, diese auch dort erzeugt werden müssen. (...) Nur Dinge die in der Execute-Methode erstellt werden sind auch wirklich im Thread-Kontext, und gerade bei so manchen Systemressourcen, und insbesondere bei GDI-Zeug scheint das recht wichtig zu sein. (...) Und so lange man ein Bitmap in Thread-Kontext im selben Kontext auf die Platte schreibt, und nicht etwa noch fix auf einem Formular darstellen will, muss man sich imho nichtmals um irgendwelche Synchronisierungen kümmern. (...)

Den Code hatte ich im ersten Post angehängt.
Aus diesen Gründe läuft es im Prinzip so, dass das Hauptprogramm die Bitmaps als Dateien im Temp-Verzeichnis ablegt. Dem Thread übergebe ich jeweils nur den Dateinamen als String.
In
Delphi-Quellcode:
Execute
erzeuge ich dann in jeder Schleife ein Bitmap. Verkürzt sieht das so aus:
Delphi-Quellcode:
Procedure TWorkThread.Execute;
Var
   I     : Integer;
   aBMP  : TBitmap;
Begin
   While (Not Terminted) Do
   Begin
      For I:=0 To Pred(Length(fArray)) Do
      Begin
         If (Not fArray[I].Done) Then
         Begin
            fArray[I].Done:= True;
            aBMP:= TBitmap.Create;
            Try
               aBMP.LoadFromFile(fArray[I].FileName);
               With TPngImage.Create Do
               Try
                  Assign(aBMP); // Bild übernehmen
                  SaveToFile(fArray[I].DestName);
               Finally
                  Free;
               End;
            Finally
               aBMP.Free;
            End;
         End;
      End;
   End;
End;

Schwedenbitter 19. Jan 2016 06:38

AW: Thread mit komischem Verhalten
 
Danke nochmal für die zahlreichen Antworten.
Zitat:

Zitat von Luckie (Beitrag 1327421)
Nur um Klarheit zu bekommen. Man kann kein Bitmap-Objekt in einem Thread außer dem Hauptthread erstellen?

Das kann ich mir nicht vorstellen. Anderenfalls wäre zu erwarten gewesen, dass im Hilfetext zumindest irgend ein Sterbenswörtchen zu lesen wäre. Ist es aber nicht. Nichtsdestotrotz werde ich mir mal graphics32.org ansehen. Am Ende ist mir wichtig, dass es irgendwie funktioniert und nicht warum - leider.

Sir Rufo 19. Jan 2016 09:05

AW: Thread mit komischem Verhalten
 
@Medium

Das Problem hängt mit der Koppelung zwischen
Delphi-Quellcode:
TBitmap
und
Delphi-Quellcode:
TCanvas
zusammen. Der Canvas selber wird allerdings lazy erstellt (was manchmal selbst zu seltsamen Ergebnissen führt, die sich durch ein einfaches
Delphi-Quellcode:
myBitmap.Canvas;
lösen können.

Delphi-Quellcode:
TCanvas
ist nicht thread-safe und kann auch nicht thread-safe verwendet werden (intern gibt es da globale Abhängigkeiten) und darum ist
Delphi-Quellcode:
TBitmap
nicht thread-safe.

Was allerdings nicht heißt, dass es keine Anwendungen gibt, die ein
Delphi-Quellcode:
TBitmap
in einem Thread verwursten und es sogar funktioniert. Die haben einfach nur Glück wenn es funktioniert. Diese "race conditions" tauchen auf, wenn sie wollen und nicht wenn man es von ihnen erwartet ;)

Der schöne Günther 19. Jan 2016 09:13

AW: Thread mit komischem Verhalten
 
Zitat:

Zitat von Schwedenbitter (Beitrag 1327429)
Das kann ich mir nicht vorstellen. Anderenfalls wäre zu erwarten gewesen, dass im Hilfetext zumindest irgend ein Sterbenswörtchen zu lesen wäre. Ist es aber nicht.

Genau darüber habe ich mich neulich auch gewundert:

Zitat:

Zitat von Der schöne Günther (Beitrag 1317616)
War mir persönlich auch vollkommen neu. Haben wir alle die Doku nicht richtig gelesen oder steht das da schlichtweg nicht drin?

Siehe: http://www.delphipraxis.net/186810-t...ml#post1317616


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:25 Uhr.
Seite 1 von 2  1 2      

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