AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Threads und TBitmaps

Ein Thema von TheGroudonx · begonnen am 12. Aug 2014 · letzter Beitrag vom 10. Okt 2017
Antwort Antwort
Seite 5 von 8   « Erste     345 67     Letzte »    
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#41

AW: Threads und TBitmaps

  Alt 1. Sep 2014, 17:28
Was für Fehler kommen da? Bist du sicher, dass die nicht damit zusammen hängen, dass du da reichlich Speicherlecks produzierst? Oder mit dem Abspeichern?
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#42

AW: Threads und TBitmaps

  Alt 1. Sep 2014, 17:36
@Medium danke für den Hinweis auf das fehlende Free, aber damit hat es nicht zu tun, wenn du die Bitmaps anschaust siehst Du was ich meine.
Angehängte Grafiken
Dateityp: jpg 14.jpg (1.017 Bytes, 17x aufgerufen)
Dateityp: jpg 15.jpg (1,2 KB, 17x aufgerufen)
Dateityp: jpg 16.jpg (879 Bytes, 16x aufgerufen)
Dateityp: jpg 20.jpg (1,2 KB, 13x aufgerufen)
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Whookie

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

AW: Threads und TBitmaps

  Alt 1. Sep 2014, 20:44
Also auch das Beispiel geht bei mir einwandfrei...


Delphi-Quellcode:
procedure TTestThread.Execute;
var
 bmp :TBitmap;
 i:Integer;
begin
   bmp :=TBitmap.Create;
   bmp.Canvas.Lock;
   bmp.Width := 100;
   bmp.Height := 100;
   bmp.Canvas.Pen.Color := clBlue;
   for I := 0 to 100 do
   begin
     bmp.Canvas.MoveTo(0,0);
     bmp.Canvas.LineTo(100,i);
   end;
   bmp.SaveToFile('C:\temp\test\' + Ffn );
   bmp.Free;
end;
mit 200 Threads probiert (auch wenn des sinnbefreit ist..)
Whookie

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

Registriert seit: 21. Mai 2014
44 Beiträge
 
#44

AW: Threads und TBitmaps

  Alt 3. Sep 2014, 12:38
...wie gesagt wenn du korrekt lockst/unlockst geht das (zumindestens bei mir unter xe5) problemlos...


Delphi-Quellcode:
procedure TPaintThread.Execute;
begin
 While (Terminated = False) do
 begin
   MyBild.Canvas.lock;
   Original.Canvas.Lock;
   try
     MyBild.Width := random(500) + 500;
     MyBild.Height := random(500) + 500;
     MyBild.Canvas.Draw(random(25) + 1, random(25) + 1, Original);
     MyBild.Canvas.Rectangle(random(25) + 1, random(25) + 1, random(50) + 25, random(50) + 25);
   finally
     MyBild.Canvas.unlock;
     Original.Canvas.Unlock;
   end;
   Synchronize(Zeichnen);
 end;
end;
Ich musste leider feststellen, dass, wenn man diesen Code eine Weile durchsteppen lässt, es zu einer EAccessviolation kommt.
Diese findet allerdings nicht im Threadablauf, sondern im Prozess der Hauptform statt, während das Bild per Synchronize gezeichnet wird.
Diese EAccessViolation findet sogar dann statt, wenn man den Code so abändert:
Delphi-Quellcode:
procedure TPaintThread.Execute;
begin

 While (Terminated = False) do
 begin

  try

  Synchronize(Zeichnen);

  finally

  end;


 sleep(1);
 
 end;
end;



procedure TPaintThread.Zeichnen;
begin
//
end;
Das bedeutet, dass allein das Aufrufen der (leeren) Synchronize-Methode einen EAccess-Error hervorruft, zumal nichts anderes der Auslöser sein kann.
Versteht ihr, was da schief läuft?
(Der Fehler kommt oft nach einigen Sekunden, manchmal aber auch garnicht)
Miniaturansicht angehängter Grafiken
fehler.jpg  

Geändert von TheGroudonx ( 3. Sep 2014 um 12:47 Uhr)
  Mit Zitat antworten Zitat
TheGroudonx

Registriert seit: 21. Mai 2014
44 Beiträge
 
#45

AW: Threads und TBitmaps

  Alt 3. Sep 2014, 12:58
Ich habe das jetzt nochmal erweitert getestet und festgestellt, dass es nicht an der Snchronize-Methode liegt.
JEDE Kommunikation von MainForm zu Thread per Prozedur kann (nach 10-100 Aufrufen im Mittel) diese Access-Violation beim Durchsteppen auslösen.
Was ich mich jetzt frage ist:
-Wieso kommt es dazu?
-Lässt es sich vermeiden? (Vermutlich nicht)
-Hat die Fehlermeldung beim Durchsteppen auch Relevanz beim normalen Ablauf des Programms?
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#46

AW: Threads und TBitmaps

  Alt 3. Sep 2014, 13:36
Also wir müssen uns hier auf eine korrekte Sprache einigen, denn sonst weiß keiner was wirklich gemeint ist. Beim Thema Multithreading ist das einfach unerlässlich.

Es kommt immer auf den Thread-Kontext an.

Wenn du also bei irgendetwas im Bereich Multithreading Probleme hast, dann ist es sehr wichtig, dass du dabei den Thread-Kontext mit angibst, und nicht welche Form da was aufruft.

Auch die Methode einer Form kann in jedem beliebigen Thread-Kontext aufgerufen werden, niemand hindert dich daran. Greifst du in irgendeinem Thread-Kontext <> MainThread-Kontext auf die VCL zu, dann kann es rummsen - das ist ja das Gemeine, es rummst nicht immer

Den aktuellen Thread-Kontext fragt man ganz einfach mit TThread.CurrentThread.ThreadID ab (bei Delphi 7 war das GetCurrentThreadID oder so) und den MainThread-Kontext mit MainThreadID . Sind die beiden Werte unterschiedlich, dann ist man eben nicht im MainThread-Kontext.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
TheGroudonx

Registriert seit: 21. Mai 2014
44 Beiträge
 
#47

AW: Threads und TBitmaps

  Alt 3. Sep 2014, 13:55
Also wir müssen uns hier auf eine korrekte Sprache einigen, denn sonst weiß keiner was wirklich gemeint ist.

Es kommt immer auf den Thread-Kontext an.

Wenn du also bei irgendetwas im Bereich Multithreading Probleme hast, dann ist es sehr wichtig, dass du dabei den Thread-Kontext mit angibst, und nicht welche Form da was aufruft.MainThreadID . Sind die beiden Werte unterschiedlich, dann ist man eben nicht im MainThread-Kontext.
Ich nahm an, dass bei einer Kombination aus dem üblichen Mainform-Prozess und einem Thread keine Verwechslungen durch Vokalwahl auftreten könnten.
Meines Wissens führt der Thread alles selbstständig aus, was über seine Routine Execute verbunden ist und kein Synchronize ist.

Jedenfalls ruft der Hauptprozess eine leere Methode des Threads auf, was zu einem Fehler führt. (siehe oben!)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#48

AW: Threads und TBitmaps

  Alt 3. Sep 2014, 14:01
Jedenfalls ruft der Hauptprozess eine leere Methode des Threads auf, was zu einem Fehler führt. (siehe oben!)
Es gibt ja nur einen Prozess und innerhalb dessen mehrere Threads.

Also wer ruft jetzt in welchem Thread-Kontext was auf?

Delphi-Quellcode:
procedure TPaintThread.Execute;
begin
  While (Terminated = False) do
  begin
    try
      Synchronize( Zeichnen );
    finally
    end;
    sleep(1);
  end;
end;

procedure TPaintThread.Zeichnen;
begin
  //
end;
PS
Wenn die TPaintThred.Execute Methode im MainThread-Kontext aufgerufen wird (weil du diese Methode direkt aufrufst), dann ist es kein Wunder, dass du da Probleme bekommst, denn vom MainThread-Kontext aus Synchronize aufrufst, dann kann das zu Problemen führen, wie es auch in der Dokumentation angegeben ist.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo ( 3. Sep 2014 um 14:04 Uhr)
  Mit Zitat antworten Zitat
TheGroudonx

Registriert seit: 21. Mai 2014
44 Beiträge
 
#49

AW: Threads und TBitmaps

  Alt 3. Sep 2014, 14:15
Der normale Mainthread-Context erstellt den Thread(TThread)-von da aus läuft alles von selbst weiter.
Der Thread(TThread) ist in einer separaten Unit.
Er(Der Thread) arbeitet seine Execute Methode ab.
Dabei ruft er die Synchronize(Zeichnen) Prozedur auf, durch welche der Mainthread-Context die Zeichen-Routine ausführt.
Dies führt nach Wiederholungen beim Durchsteppen zu einem EAccess-Violation Fehler.
Dieser Fehler passiert, da die Zeichenmethode per Synchronize aufgerufen wird, im Mainthread-Context, wobei die Abbruchstelle am Ende der Zeichenroutine(leer) in der Thread-Unit ist.

Geändert von TheGroudonx ( 3. Sep 2014 um 14:22 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#50

AW: Threads und TBitmaps

  Alt 3. Sep 2014, 14:27
Kann ich so nicht nachvollziehen, läuft wie erwartet

EDIT Überwachung des Thread-Kontexts
Delphi-Quellcode:
unit PaintThread;

interface

uses
  Classes;

type
  TPaintThread = class( TThread )

  private
    procedure Zeichnen;
  protected
    procedure Execute; override;
  end;

implementation

uses
  SysUtils,
  Windows;

{ TPaintThread }

procedure TPaintThread.Execute;
begin

  if MainThreadID = GetCurrentThreadId
  then
    raise Exception.Create( 'Upps, ich darf nicht im MainThread-Kontext sein!' );

  inherited;
  while not Terminated do
    begin
      Synchronize( Zeichnen );
      Sleep( 1 );
    end;
end;

procedure TPaintThread.Zeichnen;
begin
  if MainThreadID <> GetCurrentThreadId
  then
    raise Exception.Create( 'Upps, ich bin nicht im MainThread-Kontext!' );

end;

end.
Delphi-Quellcode:
unit FormMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, Dialogs,
  PaintThread;

type
  TForm1 = class( TForm )
  private
    FPaintThread : TPaintThread;
  public
    procedure AfterConstruction; override;
    procedure BeforeDestruction; override;
  end;

var
  Form1 : TForm1;

implementation

{$R *.dfm}
{ TForm1 }

procedure TForm1.AfterConstruction;
begin
  inherited;
  FPaintThread := TPaintThread.Create( False );
end;

procedure TForm1.BeforeDestruction;
begin
  inherited;
  FPaintThread.Free;
end;

end.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo ( 3. Sep 2014 um 14:33 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 5 von 8   « Erste     345 67     Letzte »    

 

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 12:53 Uhr.
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