![]() |
Delphi-Version: 5
Threadübergreifende Bitmap
Liste der Anhänge anzeigen (Anzahl: 1)
Guten Tag,
Folgendes Problem: 1. Thread: GUI und erstellung des 2 Threads. Besitzt eine Bitmap B, die regelmäßig auf eine Paintbox auf der Form gezeichnet wird 2. Thread: Malt die aktuelle Uhrzeit auf eine Bitmap C und malt die Bitmap C synchonisiert auf B. Problem dabei: drücke ich auf start, sehe ich die Zeit so laufen wie sie soll. Bewege ich aber die Maus über die Form, so bleibt die Zeit stehen (nicht der Thread, wurde getestet). Wieso läuft es dann nicht normal weiter? Ebenso steigt der benötigte Arbeitsspeicher exponentiell an wenn die Maus sich über der Form befindet. Einen solchen Fehler hatte ich noch nie :? Deshalb bitte ich euch um Hilfe mit freundlichen Grüßen FirstTry P.S: Datei mit Quellcode (kompiliert unter Delphi 7 PE )ist im Anhang Das Problem ist schon auf das notwendigste reduziert. |
AW: Threadübergreifende Bitmap
Das Programm verstehe ich nicht.
Um nur eine Uhrzeit anzuzeigen, muss man das nicht auf die umständlichste Art tun.
Delphi-Quellcode:
while not Terminated do
begin aBild.Canvas.TextOut( 100, 100, FormatDateTime('hh:nn:ss.zzz', Now) ); //aktualisiere Daten Synchronize( Zeichne ); Sleep(20); // <---------------------- end; |
AW: Threadübergreifende Bitmap
Vielen Dank für deine Antwort!
Synchronize ist also nicht blockierend, ist das das Problem ?! Es geht hier nicht um die Uhrzeit, aber zur Vereinfachung des Problems auf das Wesentliche habe ich versucht ein Testprojekt zu schreiben, indem der Fehler den ich meine Sichtbar wird. Bei sleep(20) hält er trotzdem noch manchmal an... wielange muss ich denn warten? kann ich WaitFor oder sonst etwas verwenden, um genau die notwendige Zeit zu warten? |
AW: Threadübergreifende Bitmap
Hallo FirstTry, Willkommen in der DP.
Zitat:
Danach wundert es mich eigentlich mehr, dass es am Anfang, bevor du die Maus über die Paintbox bewegst, laut deiner Aussage noch funktioneren soll. Denn du updatest zwar das TBitmap im Speicher (FBild), aber ich kann in deinem Code nirgends eine Stelle finden, in der du ein Neuzeichnen der Paintbox veranlasst. Somit wird das Bitmap zwar fleißig aktualisiert, aber vergammelt dann im Speicher, ohne dass du es jemals zu Gesicht bekommst. Dass der Speicherverbrauch explodiert, kann ich auch nicht nachvollziehen. Grundsätzlich können solche Dinge schon passieren, wenn man auf GDI-Objekte wie TBitmap oder TCanvas fälschlicherweise mit mehreren Threads parallel zugreift. Aber da du Synchronize verwendest, sollte es hier eigentlich zu keinen Problemen kommen. Hast du das Problem wirklich mit dem Projekt, so wie du es angehängt hast, reproduziert? Zitat:
Bitte nicht irgendwas mit Sleep hinfrickeln! Selbst wenn es für eine Zeit lang zu funktionieren scheint, irgendwann fliegt es dir dafür so richtig um die Ohren. |
AW: Threadübergreifende Bitmap
Zitat:
Zitat:
|
AW: Threadübergreifende Bitmap
Ohne genaue Diagnose, sondern nur aus der Erfahrung und meinem bescheidenen Wissen:
Der Speicher explodiert, weil du immer das Bitmap neu erzeugst, aber nicht wieder frei gibst. Das Programm "hakt" weil es die Mouse-Messages abarbeitet und somit nicht den Programmcode oder sonstige Eingaben abarbeiten kann. Beispiel: Fenster an der Titelleiste "anfassen" und wild hin und her schieben. Es wird nichts machen, weil es nur mit dem Neu-Zeichen beschäftigt ist. Ok. Mein Wissen beruht noch auf Windows XP. Microsoft hat ab Vista ziemlich was am Fenstermanager gedreht. Aber wenn man wie unter XP programmiert, sollte man auf der sicheren Seite sein. |
AW: Threadübergreifende Bitmap
Danke Luckie für deinen Beitrag.
Allerdings bin ich mir nicht sicher ob du überhaupt einen Blick in den Code geworfen hast. 1. Das Bitmap wird nur 1mal erzeugt 2. Steigt der Speicher nur wenn die Maus über der Form ist 3. Verarbeite ich die Mausbewegung nichteinmal (nur die normalen Windows Events, kein Code von mir) Wie programmiert man denn unter XP? :?: |
AW: Threadübergreifende Bitmap
Öhm. Nein. Habe keine Blick drauf geworfen. Habe die angehängte Datei nicht gesehen.
Wie man unter XP die grafischen Sachen programmiert? XP zeichnet nur das auf dem Desktop, was man auch sieht. Vista und höher speichern das irgendwie im Hintergrund, was auf dem Desktop gezeichnet werden soll. |
AW: Threadübergreifende Bitmap
Guten Tag,
Es kommt teilweise der Fehler: 'Leinwand/Bild erlaubt kein Zeichnen' Vielleicht wird zu schnell gemalt oder zu oft.. Ich weiß leider immer noch nicht, wo der Fehler genau steckt. Scheinbar im Synchronize, aber auch ein Test zeigte, dass Synchronize blockierend ist, also weiß ich nicht was es für Fehler geben könnte. Wird möglicherweise "Canvas.Draw" von einem anderen Thread ausgeführt der ebenfalls für die Mausverarbeitung über der Form zuständig ist? Wenn ja, wie kann ich das beheben? |
AW: Threadübergreifende Bitmap
Du zeichnest NIE auf die PaintBox...
|
AW: Threadübergreifende Bitmap
Zitat:
Code:
wird in einem Timer alle 10 ms aufgerufen. (Steht oben auch schon)
procedure TForm1.PaintBox1Paint(Sender: TObject);
begin Paintbox1.Canvas.Draw(0,0, FBild); end; Wieso sollte es sonst auch bis zu der Mausbewegung funktionieren?! |
AW: Threadübergreifende Bitmap
Zitat:
Und die VCL baut hier (aus verständlichen Gründen) keinen Threadschutz um den Zugriff herum. Die sporadischen Fehlermeldungen sind eigentlich nur Zufällig funktionierende Zugriffe. |
AW: Threadübergreifende Bitmap
OK...
Timer 10ms geht nicht.. Vergiss den Timer... Folgendes ist zu ändern:
Delphi-Quellcode:
Im Thread noch setzen "vor der While"
aBild.Canvas.Font.Name := 'Arial';
Dann Uses Unit1 in Unit2 und
Delphi-Quellcode:
Schon funktioniert es!
procedure TTestThread.Zeichne;
begin FBild.Canvas.StretchDraw( Rect(0,0,FBild.Width,FBild.Height), aBild ); Form1.Paintbox1.Canvas.Draw(0,0, FBild); // neu end; |
AW: Threadübergreifende Bitmap
Zitat:
Jedes Zeichnen aus dem Thread auf im Hauptprogramm erzeugte Formulare kracht früher oder später. |
AW: Threadübergreifende Bitmap
Zitat:
Zitat:
Und zusätzlich habe ich dann eine (kleine) Kreuzreferenz zwischen Unit1 und 2, Zeichne unnötigerweise auf ein Zwischenbitmap, da ich von der GUI ja nicht neuzeichnen sollte und abgesehen davon ist es echt nicht schön von einer Klasse auf die "höhere" Klasse zuzugreifen. Zitat:
Das sehe ich auch so, deshalb möchte ich die Zeichnung nur "irgendwie" (aber ordentlich!) rüberkriegen... Danke für eure Hilfe, leider hat keiner einen funktionierenden Lösungsansatz bishher liefern können. |
AW: Threadübergreifende Bitmap
Zitat:
Probier doch mal statt TBitmap TPngImage. |
AW: Threadübergreifende Bitmap
TPngImage gibts erst ab XE7 wenn ich das richtig sehe.
Ich arbeite noch mit der Steinzeitversion 7 |
AW: Threadübergreifende Bitmap
Zitat:
Falls du TMS einsetzt, diese haben eine eigene Implementierung (haben die OpenSource-Version lizenziert bevor Emba diese gekauft hat). |
AW: Threadübergreifende Bitmap
TPngImage sollte seit Delphi 2009 enthalten sein.
Das Original von Gustavo Daud sollte auch mit Delphi 7 funktionieren, wenn du es noch irgendwo findest. |
AW: Threadübergreifende Bitmap
Habe den Link gefunden
Code:
Also liegt der Fehler in der Verarbeitung von WindowsHandles?
http://www.snehovapohotovost.cz/authorsmore.php?id=6929
Es kann doch nicht sein, dass mein Fehler nicht "normal" lösbar ist... Sicher dass es am Bitmap liegt? Könnte es anstatt mit Synchronize mit irgendetwas anderem klappen? |
AW: Threadübergreifende Bitmap
Ich habe selber auch grade so etwas probiert, bekomme ständig "Out of resources". Siehe auch hier:
![]() Ohne im Quelltext zu wühlen, dafür aber die Suchmaschine meines Vertrauens zu befragen, sieht es (zumindest für Laien wie mich) wirklich danach aus, als könnte man mit Vcl.Graphics.TBitmap nur im Hauptthread arbeiten? :| |
AW: Threadübergreifende Bitmap
Zitat:
|
AW: Threadübergreifende Bitmap
Also ich habe in die While-not-terminated-Schleife ein Sleep eingebaut und die Instantiierung des Bitmaps in den Konstruktor des Threads verlagert. Klappt.
|
AW: Threadübergreifende Bitmap
Zitat:
|
AW: Threadübergreifende Bitmap
Nur das Sleep verbessert die Situation. Die Bitmap Instanz kann man erzeugen wo man möchte.
Problematisch ist nicht
Delphi-Quellcode:
an sich, sondern
TBitmap
Delphi-Quellcode:
. Da wird intern etwas Globales verwendet und das fällt einem auf die Füße.
TBitmap.Canvas
Ein
Delphi-Quellcode:
/
TCanvas.Lock
Delphi-Quellcode:
sollte eigentlich helfen, aber leider auch nur bedingt. Irgendwann kommt man in einen Deadlock, wenn das zu schnell von unterschiedlichen Threads erfolgt.
TCanvas.Unlock
Darum bringt die Verwendung von
Delphi-Quellcode:
eine Verbesserung.
Sleep
Wenn man eine echte Lösung haben möchte, dann sollte man
Delphi-Quellcode:
im Thread vergessen und dort auf
TBitmap
Delphi-Quellcode:
von
TBitmap32
![]() Zu dieser Erkenntnis kommt man auch hier: ![]() |
AW: Threadübergreifende Bitmap
Zitat:
Aber was solls mit TBitmap32 oder TPngImage gibts genügend Alternativen. |
AW: Threadübergreifende Bitmap
Zitat:
Delphi-Quellcode:
oder
TBitmap.Scanline
Delphi-Quellcode:
zu arbeiten (was über Scanline geht).
TBitmap.Pixels
|
AW: Threadübergreifende Bitmap
Zitat:
|
AW: Threadübergreifende Bitmap
Zitat:
Da aber Thread und
Delphi-Quellcode:
nicht so richtig zusammen passen, sollte man das getrost mit einem Sperrvermerk belegen und im Thread auf eine der genannten Alternativen setzen. Ein Sleep in einem Thread ist eher Makulatur und keine stabile Grundlage. Das ist nur legitim um solche Timingprobleme zu lokalisieren.
TBitmap
|
AW: Threadübergreifende Bitmap
Zitat:
|
AW: Threadübergreifende Bitmap
Zitat:
|
AW: Threadübergreifende Bitmap
Zitat:
|
AW: Threadübergreifende Bitmap
Zitat:
|
AW: Threadübergreifende Bitmap
Zitat:
Es wird im HauptThread die Paitbox gezeichnet bzw. auf die Paintbox... Es wird lediglich der grafische Inhalt von A nach B Kopiert... Also alles gut, daher Funktioniert es ja nach meinen Änderungen |
AW: Threadübergreifende Bitmap
Zitat:
|
AW: Threadübergreifende Bitmap
Zitat:
Ok egal - ich bin raus... Mavarik PS : ![]() |
AW: Threadübergreifende Bitmap
Vielen Dank für eure Hilfe!
Mit TBitmap32 funktioniert alles einwandfrei. Wäre nett wenn mir jemand dazu gute Tutorials/ Beispiele liefern könnte. Ansonsten sehe ich diesen Thread als geschlossen :) Abschließend: TBitmap (oder sonst etwas, dass TCanvas nutzt) sollte nicht in Threads verwendet werden. |
AW: Threadübergreifende Bitmap
War mir persönlich auch vollkommen neu. Haben wir alle die Doku nicht richtig gelesen oder steht das da schlichtweg nicht drin?
|
AW: Threadübergreifende Bitmap
Zitat:
![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:02 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz