Autor |
Beitrag |
hui1991
      
Beiträge: 433
Windows XP, WIndows Vista
Turbo Delphi Explorer| Delphi, PHP,Blitzbasic
|
Verfasst: So 10.08.08 15:18
Hallo,
ich codiere mit meinem Programm Daten in ein anderes Format. Dies mache ich mit Threads. Der Hauptthread ist dazu da das Fenster neuzuzeichnen. Der andere Thread berechnet die Daten.
Bei den Informationen ist aber hin und wieder ein Fehler beim Zeichnen.
Manchmal wird die Schrift zu groß gezeichnet.
Kann es daran liegen, genau in dem moment der andere Thread die Anzeige aktualisiert und der Hauptthread das Label neuzeichnet.
Im Anhang wird gezeigt wie es groß und wie es normal aussieht.
Meine Frage ist nun: Wie kann ich es beseitigen?
Edit: Gerade bekam ich eine Fehlermeldung die unten als Screen ist und da steht:
Quelltext 1:
| Im Projekt ist eine Exeception der Klasse EInvalidOperation mit der Meldung 'Leinwand/Bild erlaubt kein Zeichnen' aufgetreten. |
Wie bekommt man den Fehler weg so das sich die 2 Threads nicht im Weg stehen?
MfG
hui1991
Einloggen, um Attachments anzusehen!
|
|
Hidden
      
Beiträge: 2242
Erhaltene Danke: 55
Win10
VS Code, Delphi 2010 Prof.
|
Verfasst: So 10.08.08 16:06
Hi,
Mal so ven dem her, was ich bisher von Threads gehört habe: Lass doch den Hauptthreat die Daten SYNCHRONISIERT aus deinem Threat auslesen und die Form auch ausschließlich von der Hauptanwendung bearbeiten.
mfG,
_________________ Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
|
|
Sinspin
      
Beiträge: 1335
Erhaltene Danke: 118
Win 10
RIO, CE, Lazarus
|
Verfasst: So 10.08.08 16:39
Ein Thread darf niemals einfach so auf ein Fenster zugreifen und irgendwelche Eigenschaften von Komponenten ändern.
Wenn du über Delphi : Datei / Neu / Thread-Object einen Neuen Thread erstellst, dann steht das ganz deutlich als Kommentar in der neuen Unit.
Delphi-Quelltext
Allgemein:
Eine Möglichkeit ist es, unter Verwendung von Syncronize aus deinem Thread heraus zu aktualisieren. Die bessere Lösung.
Die andere Möglichkeit ist, die Aktualisierung über deine Fenster zu realisieren. Unter Verwendung eines Timers oder OnIdle. Da kann es aber immer mal passieren das du einen Thread zu einem ungünstigen Zeitpunkt erwischst. Also, die schlechtere Lösung.
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
hui1991 
      
Beiträge: 433
Windows XP, WIndows Vista
Turbo Delphi Explorer| Delphi, PHP,Blitzbasic
|
Verfasst: So 10.08.08 16:59
Ich hab den Thread als Code erstellt. Ich hab gerade die Werte mit:
InterlockedExchange
geändert.
Das hab ich aus dem Thema: www.delphi-library.d...20%20synchronisieren
Stand in der PDF drin, scheint auch zu funktionieren.
Ich schreibe es auf Synchronize um.
Problem ist nur wie bekomme ich die Werte von meiner Thread-Funktion in die Procedure?
Edit:
Ich werde einfach einen Record erstellen und dort alle Daten eingeben. Wenn ich den Synchronize-Befehl aufrufe, dann werden die Daten gelesen und eingetragen.
Hoffe das geht so.
|
|
Sinspin
      
Beiträge: 1335
Erhaltene Danke: 118
Win 10
RIO, CE, Lazarus
|
Verfasst: So 10.08.08 17:18
Ich verwende dafür immer zwei Prozeduren.
Eine, und zwar die, die im Thread aufgerufen wird, hat Parameter. Die speichert die bekommenen Werte in, unter private im Thread liegenden Variablen.
Und ruft im Anschluss die Andere, Parameterlose via Synchronize auf.
Die Parameterlose holt sich dann die Variablen und aktualisiert die Ansicht.
Das ist zwar nicht unbedingt schön, ist aber die einzige Lösung die mir dazu einfällt.
// Edit: bist ja schon selber drauf gekommen 
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
hui1991 
      
Beiträge: 433
Windows XP, WIndows Vista
Turbo Delphi Explorer| Delphi, PHP,Blitzbasic
|
Verfasst: So 10.08.08 17:40
Ich kann Synchronize nicht aufrufen.
Meine Threadfunktion sieht so aus:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
| procedure UpdateComponents; begin Form1.ProgressBar1.Max := Fensterinfo.ProgressBar1Max; Form1.ProgressBar1.Position := Fensterinfo.ProgressBar1Positon; Form1.Label5.Caption := Fensterinfo.Label5Caption; Form1.Panel2.Caption := Fensterinfo.Panel2Caption; Form1.Panel3.Caption := Fensterinfo.Panel3Caption; end;
function ThreadFunc(tp: PThreadParams): Integer; var Open : string; Save: string; begin Open := PThreadParams(tp)^.Open; Save := PThreadParams(tp)^.Save;
Synchronize(UpdateComponents); Dispose(tp); end; |
in der Delphi-Hilfe steht:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure TMyThread.PushTheButton; begin Button1.Click; end; ... procedure TMyThread.Execute; begin ... Synchronize(PushTheButton); ... end; |
Irgendwie funktioniert Synchronize nicht mit einer funktion.
Ich rufe die Funktion so auf:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| var Thread : THandle; ThreadID : Cardinal; begin Thread := BeginThread(nil, 0, @ThreadFunc, nil, 0, ThreadID); end; |
Ich muss wohl den Thread anders erstellen.
Oder gibt es eine andere Möglichkeit.
Probiere schon 4 Stunden an den Threads rum. In der Zeit wäre das Programm schon fertig gewesen ^^
|
|
Boldar
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: So 10.08.08 17:53
hui1991 hat folgendes geschrieben: |
An der Stelle kommt ein [Pascal Fehler] Unit1.pas(589): E2066 Operator oder Semikolon fehlt |
Dann fehlt wohl ein Semikolon!!!
Poste doch mal den ganzen Code
|
|
hui1991 
      
Beiträge: 433
Windows XP, WIndows Vista
Turbo Delphi Explorer| Delphi, PHP,Blitzbasic
|
Verfasst: So 10.08.08 18:03
Semikolon ist hinten dran. Irgendwas ist da noch falsch.
Welcher von den 3 Proceduren wird eigentlich verwendet für sowas:
Quelltext 1: 2: 3: 4: 5:
| [Delphi] procedure Synchronize(ASyncRec: PSynchronizeRecord; QueueEvent: Boolean); overload;
[Delphi] procedure Synchronize(AMethod: TThreadMethod); overload;
[Delphi] procedure Synchronize(AThread: TThread; AMethod: TThreadMethod); overload; |
Zuletzt bearbeitet von hui1991 am So 10.08.08 18:32, insgesamt 5-mal bearbeitet
|
|
Boldar
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: So 10.08.08 18:23
|
|
hui1991 
      
Beiträge: 433
Windows XP, WIndows Vista
Turbo Delphi Explorer| Delphi, PHP,Blitzbasic
|
Verfasst: So 10.08.08 18:32
Ich hab mal einen Thread umgeschrieben auf:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
| procedure UpdateComponents; begin Form1.ProgressBar1.Max := Unit1.Fensterinfo.ProgressBar1Max; Form1.ProgressBar1.Position := Unit1.Fensterinfo.ProgressBar1Positon; Form1.ProgressBar2.Max := Unit1.Fensterinfo.ProgressBar2Max; Form1.ProgressBar2.Position := Unit1.Fensterinfo.ProgressBar2Positon; Form1.Label5.Caption := Unit1.Fensterinfo.Label5Caption; Form1.Panel2.Caption := Unit1.Fensterinfo.Panel2Caption; Form1.Panel3.Caption := Unit1.Fensterinfo.Panel3Caption; end;
procedure Threadladen.Execute; var s : string; x,y: Integer; begin Unit1.Fensterinfo.Panel2Caption := 'Status: Anwendung laden...'; Unit1.Fensterinfo.ProgressBar2Max:=100; Unit1.hin_daten := TStringlist.Create; Unit1.Fensterinfo.ProgressBar2Positon:=2; Unit1.hin_leistung := TStringlist.Create; Unit1.Fensterinfo.ProgressBar2Positon:=4; Unit1.hin_daten.LoadFromFile('2.joined'); Unit1.Fensterinfo.ProgressBar2Positon:=74; Unit1.hin_leistung.LoadFromFile('1.joined'); Synchronize(UpdateComponents); end; |
Dieses Synchronize hat bei mir bis jetzt nie funktioniert.
Edit: Hab einen neuen beitrag erstellt, weil delphi-tag sonst nicht funktioniert.
|
|
Sinspin
      
Beiträge: 1335
Erhaltene Danke: 118
Win 10
RIO, CE, Lazarus
|
Verfasst: So 10.08.08 18:36
Warum blos immer alle so giergig auf den Quelltext anderer Leute sind!?
Ich vermute mal das es daran liegt das die Prozedur aus der du den Aufruf machst nicht zu Thread gehört und damit Synchronize unbekannt ist. Denn Synchonize ist eine Prozedur des Threads!
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
hui1991 
      
Beiträge: 433
Windows XP, WIndows Vista
Turbo Delphi Explorer| Delphi, PHP,Blitzbasic
|
Verfasst: So 10.08.08 18:46
Ich hab den Fehler gefunden.
Das muss so heißen
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| class procedure Threadladen.UpdateComponents; begin Form1.ProgressBar1.Max := Unit1.Fensterinfo.ProgressBar1Max; Form1.ProgressBar1.Position := Unit1.Fensterinfo.ProgressBar1Positon; Form1.ProgressBar2.Max := Unit1.Fensterinfo.ProgressBar2Max; Form1.ProgressBar2.Position := Unit1.Fensterinfo.ProgressBar2Positon; Form1.Label5.Caption := Unit1.Fensterinfo.Label5Caption; Form1.Panel2.Caption := Unit1.Fensterinfo.Panel2Caption; Form1.Panel3.Caption := Unit1.Fensterinfo.Panel3Caption; end;
procedure Threadladen.Execute; var s : string; x,y: Integer; begin Unit1.Fensterinfo.Panel2Caption := 'Status: Anwendung laden...'; Unit1.Fensterinfo.ProgressBar2Max:=100; Unit1.hin_daten := TStringlist.Create; Unit1.Fensterinfo.ProgressBar2Positon:=2; Unit1.hin_leistung := TStringlist.Create; Unit1.Fensterinfo.ProgressBar2Positon:=4; Unit1.hin_daten.LoadFromFile('2.joined'); Unit1.Fensterinfo.ProgressBar2Positon:=74; Unit1.hin_leistung.LoadFromFile('1.joined'); Synchronize(UpdateComponents); end; |
1. Es muss in ein Thread-Objekt
2. Es muss eine Class Procedure sein.
dann geht es.
Die Lösung habe ich hier gefunden:
www.delphipraxis.net/topic91117.html
Eigentlich sollte als Fehlermeldung:
[Pascal Fehler] Unit1.pas(440): E2076 Diese Form des Methodenaufrufs ist nur für Klassenmethoden erlaubt
kommen, aber es kommt nur mit TThread.Synchronize
|
|