![]() |
Delphi-Version: XE
EOutOfResource + Thread + Bitmap + Assign
Hallo,
ich wende mich wieder mal mit einem Fehler an Euch, auf dessen Schliche ich nicht komme... Ich habe einen Thread, der einen "Bild" auf ein Bitmap zeichnen soll. Dieses Bitmap soll dann in der GUI in einem Image angezeigt werden
Delphi-Quellcode:
Nach einiger Zeit, jedoch unterschiedlich, mal 10 mal 100 Timeraufrufe später, bricht er ab mit
type TDisplayHandler = class(TThread)
[...] constructor TDisplayHandler.Create(_createSuspended : Boolean); begin FBitmap := TBitmap.Create; [...] end; destructor TDisplayHandler.Destroy; begin FreeAndNil(FBitmap); [...] end; procedure TDisplayHandler.DisplayBitmap(_data : TObjectList<TTorqueData>); //-> wird von einem Timer regelmäßig aufgerufen begin FData := _Data; if FIsDone then //Graph wurde fertig berechnet, neuer kann berechnet werden FIsDone := False; end; procedure TDisplayHandler.SyncEvent; begin // if Assigned(FBitmapChangeEvent) then // FBitmapChangeEvent(FBitmap); //eigentlich so, aber dahinter steht effektiv auch nur ein: frmMain.Image.Picture.Assign(FBitmap); end; procedure TDisplayHandler.Execute; begin while not Terminated do begin if not FIsDone then begin DoCreate; Synchronize(SyncEvent); FIsDone := True; end else Sleep(20); end; end; end.
Code:
Der Cursor hängt dann in der Methode
Project Torque.exe raised exception class EOutOfResources with message 'Out of system resources'.
Delphi-Quellcode:
und zwar dort an der ersten Stelle, an der ich auf das Bitmap zugreifen will
DoCreate
Delphi-Quellcode:
Ich finde meinen Fehler nicht, denn FBitmap wird ja nur einmal erstellt undd er Zugriff auf die GUI wird synchronisiert. Oder mache ich einen kapitalen Denkfehler (wäre nicht das erste Mal)?
procedure TDisplayTorqueOverTime.DoCreate;
begin [...] clearBitmap(FBitmap); drawLine(0, FXAxisPos, FWidth, FXAxisPos, clBlack, 3, FBitmap.Canvas); //hier hängt der Cursor drawLine(FYAxisPos, 0, FYAxisPos, FHeight, clBlack, 3, FBitmap.Canvas); [...] //mit procedure clearBitmap(_bitmap : TBitmap); //-> überzeichnet das Canvas des angegebenen Bitmaps weiß var t_brush : TBrush; begin if Assigned(_bitmap) then begin t_brush := Tbrush.Create; t_brush.Assign(_bitmap.Canvas.Brush); _bitmap.Canvas.Brush.Color := clWhite; _bitmap.Canvas.Brush.Style := bsSolid; _bitmap.Canvas.FillRect(Rect(0, 0, _bitmap.Width, _bitmap.Height)); _bitmap.Canvas.Brush.Assign(t_brush); t_brush.Free; end; end; procedure drawLine(_x1, _y1, _x2, _y2 : Integer; _color : TColor; _width : Integer; _canvas : TCanvas); //-> zeichnet im angegebenen Canvas eine Linie //-> Pen wird dabei nicht verändert, da er zwischengespeichert wird var t_pen : TPen; begin if Assigned(_canvas) then begin t_pen := TPen.Create; t_pen.Assign(_canvas.Pen); _canvas.Pen.Color := _color; _canvas.Pen.Width := _width; _canvas.MoveTo(_x1, _y1); _canvas.LineTo(_x2, _y2); _canvas.Pen.Assign(t_pen); t_pen.Free; end; end; Für Hilfe wäre ich wie immer immens dankbar... |
AW: EOutOfResource + Thread + Bitmap + Assign
Ich würd zunächst in die DPR an den Anfang
Delphi-Quellcode:
schreiben und dann mal die Anwendung mal manuell beenden, bevor die Exception kommt. Dann siehst du (wahrscheinlich) zumindest schon mal, was da eigentlich den Speicher zumüllt. Wo der Cursor stehen bleibt, ist nämlich wenig aussagekräftig, denn das zeigt dir ja nur, wo der Tropfen das Fass zum Überlaufen gebracht hat.
ReportMemoryLeaksOnShutdown := True
Ansonsten seh ich da jetzt auf den ersten Blick nichts. Ich denke, da ist mehr Code erforderlich, um eine Diagnose zu stellen... z.B. seh ich nirgendwo den Timer, von dem du redest. Was noch sein könnte, ist, dass innerhalb des Threads eine stille Exception auftritt, wodurch eine Routine frühzeitig abgebrochen wird, bevor ein Objekt freigegeben wird. In solchen Fällen ist Try-Finally wirklich wichtig. Du kannst ja mal einen Breakpoint in den Thread setzen um dir die Exceptions anzeigen zu lassen. |
AW: EOutOfResource + Thread + Bitmap + Assign
Danke für Deine Antwort,
Wenn ich
Delphi-Quellcode:
verwende, poppt kein Fenster auf, das mich darüber informiert, wie schlecht ich programmiere, also gehe ich davon aus, zumindest keine allzu offensichtlichen Speicherlöcher zu hinterlassen
ReportMemoryLeaksOnShutdown := True
Seltsam, sobald ich die Synchronize-Methode auskommentiere, läuft das Programm "stundenlang" fehlerfrei:
Delphi-Quellcode:
Mit anderen Worten: Das Bitmap wird nach wie vor "bemalt", jedoch nicht mehr per Assign in das Image der MainForm "kopiert",
procedure TDisplayHandler.Execute;
begin while not Terminated do begin if not FIsDone then begin DoCreate; // Synchronize(SyncEvent); //wenn das auskommentiert ist, läuft das Programm FIsDone := True; end else Sleep(20); end; end; das schließt mMn einen Fehler bei der "Speicherzumüllung" aus. Also muss mMn ein Fehler bei der Übergabe an die GUI passieren, obwohl der Zugriff darauf synchronized ist? :wiejetzt: |
AW: EOutOfResource + Thread + Bitmap + Assign
Ah halt, er sagt ja auch „System Resources“ und nicht „Memory“.
Da fällt mir ein, ich hatte glaube ich vor gar nicht all zu langer Zeit ein ähnliches Problem – ich bin mir nicht mehr 100%ig sicher, aber ich glaube es war so, dass GDI-Objekte immer einem bestimmten Thread angehören. D.h. du kannst sie nicht im einen Thread erzeugen und in einem anderen verwenden, bzw. es kann dann zu Fehlern kommen. Genau das tust du aber, weil der contructor des Threads noch im Hauptthread ausgeführt wird. Schieb die Erzeugung von FBitmap mal vom constructor in die Execute-Methode (und die Freigabe natürlich auch). Gerade im fraglichen Projekt, wo der Fehler bei mir auftrat, noch mal nachgeschaut. Vergiss das mit dem constructor. Du musst einfach nur Canvas.Lock/Unlock vor und nach deinen Zeichenoperationen aufrufen. Das war des Rätsels Lösung. Edit²: Hat zumindest bei mir gereicht. |
AW: EOutOfResource + Thread + Bitmap + Assign
Zitat:
|
AW: EOutOfResource + Thread + Bitmap + Assign
Zitat:
Seltsam, seltsam...:gruebel: Zitat:
Auf jeden Fall vielen Dank für Eure Antworten, andere Baustellen rufen mich jedoch , da jetzt diese anscheinend begradigt wurde:dp: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:28 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-2025 by Thomas Breitkreuz