![]() |
Delphi-Version: 7
Thread startet execute nicht
Hallo zusammen,
Ich befasse mich nun seit einiger Zeit mit Delphi und habe mich nun an Multithreading probiert. Das heist ich habe mir wie in diversen Anleitungen beschrieben eine neue TCheckThread Klasse von TThread abgeleitet und sie angepasst. Über das Hauptformular rufe ich nun meinen TCheckThread in 1 bis mehreren Instanzen mit verschiedenen Parametern über TCheckThread.Create auf. Genau dort kommt es zum Problem: Der Thread beginnt nicht zu arbeiten. Hier ein paar Quellcode Ausschnitte
Code:
(Hinweis: getbestreforgeid: in dieser Prozedur wird der beste Wert zwischen Start- und Endwert ermittelt und in Fresultstring geschrieben. Am Ende wird Fthreaddone auf true gesetzt, sodass die Werte über das Hauptformular ausgelesen werden.)
[...]
type TCheckThread = class(TThread) private Fstartcountarray:unit1.tcountarray; Fendstring:string; Freforgestringarray:unit1.treforgestringarray; Fthreaddone:boolean; Fresultstring:string; Fresultpoints:integer; protected function getstatname(statid:integer):string; function calcpoints(calcablestring:string):integer; procedure getbestreforgeid; procedure execute; override; public constructor Create(startcountarray:tcountarray; endstring:string; reforgestringarray:treforgestringarray); property threaddone:boolean read Fthreaddone write Fthreaddone; property resultstring:string read Fresultstring write Fresultstring; property resultpoints:integer read Fresultpoints write Fresultpoints; end; implementation constructor TCheckThread.Create(startcountarray:tcountarray; endstring:string; reforgestringarray:treforgestringarray); var i:integer; begin inherited Create(true); Fthreaddone:=false; for i:=0 to 15 do Fstartcountarray[i]:=startcountarray[i]; Fendstring:=endstring; Fresultpoints:=0; freforgestringarray:=reforgestringarray; Freeonterminate:=false; self.Resume; end; [...] procedure TCheckThread.execute; begin form1.Memo2.Lines.Add('getbestreforgeid starting'); getbestreforgeid; end; [...] Aufgerufen wird der Thread dann in einer andren Unit:
Code:
Der gesamte TCheckThread.execute wird vom Compiler weg optimiert, Ich habe schon einiges versucht, dazu aber keine Lösung gefunden. Hat irgendjemand eine Idee dazu?
calcthread[q]:=tcheckthread.Create(countarray,endstring,reforgestringarray);
|
AW: Thread startet execute nicht
Hallo und Herzlich Willkommen in den heiligen Hallen des Wissen und des Wahnsinns (oder so ähnlich).
Erst einmal Herzlichen Glückwunsch, direkt mit der TThread-Klasse zu arbeiten und nicht direkt die WinAPI-Aufrufe zu verwenden. Ich benutze mittlerweile nur noch TThreads und finde das viel komfortabler. Jedoch:
|
AW: Thread startet execute nicht
TThread.Start gibt es erst seit Delphi 2010 ;)
|
AW: Thread startet execute nicht
Bitter, ich hätte es jetzt darauf geschoben.
Die Execute-Methode überschreibt die Methode aus TThread und erstellt wird auch ein TCheckThread-Objekt, da ist alles im Grünen. Vielleicht fliegt die Methode nach dem VCL-Zugriff komplett raus? Aber dann sollte der Debugger wenigstens eine Exception anzeigen... |
AW: Thread startet execute nicht
Zitat:
Code:
p.s. möglicherweise ist damit das Problem auch bereits behoben...
constructor TCheckThread.Create(startcountarray:tcountarray; endstring:string; reforgestringarray:treforgestringarray);
var i:integer; begin inherited Create(False); ... end; (ab Delphi 6 wird der Thread erst gestartet nachdem der Konstruktor ausgeführt wurde) |
AW: Thread startet execute nicht
Ist das Self.Resume im Konstruktor so in Ordung ?
Hier gibt es auch noch ein Tutorial wo mit Synchronize auf die Oberfläche zugegriffen wird. Sollte mit Delphi genauso laufen. ![]() Mfg Ginko |
AW: Thread startet execute nicht
Zitat:
Zitat:
Zitat:
Die jetzt erwähnten Lösungsvorschläge führen aber auch alle nicht zum gewünschten Ergebnis. Es kommt nicht dazu, dass der Thread gestartet wird. Die gesammte TCheckThread.execute wird vom Compiler weg optimiert. |
AW: Thread startet execute nicht
Zitat:
Delphi-Quellcode:
denn erreicht und ausgeführt, oder ist da auch kein blauer Punkt?
calcthread[q]:=tcheckthread.Create(countarray,endstring,reforgestringarray);
|
AW: Thread startet execute nicht
ja, das wird definitiv erreicht und ausgeführt. Habe kurz davor einen Haltepunkt gesetzt und mir den Ablauf angeschaut. Auch die constructor-Prozedur wird komplett durchlaufen, blos die execute-Prozedur wird nicht gestartet.
|
AW: Thread startet execute nicht
Zitat:
Deshalb kann diese auch eigentlich nicht wegoptimiert werden. Gründe die mir einfallen: - Der gepostete Quelltext stimmt mit dem tatsächlichen nicht überein und das "override;" wurde bei der Deklaration von "Execute" vergessen. - Die Unit gehört nicht zu dem Projekt und wird deshalb nicht mehr compiliert, statt dessen wird eine alte "*.dcu" eingebunden. Unabhängig vom aktuellen Problem sind mir die Property aufgefallen. Der Zugriff auf Variablen aus mehreren Threads muss auf jeden Fall synchronisiert werden (z.B. Get- und Setmethoden mit TCriticalSection). |
AW: Thread startet execute nicht
Also wirklich helfen tut davon nichts. Ich poste mal etwas mehr Quelltext (1:1 aus Delphi kopiert):
(Im übrigen weis ich, dass sicherlich das ein oder andere etwas anders aussehen müsste oder sollte, darum kümmere Ich mich aber, wenn es vom Prinzip her erstmal läuft) Hier die procedure, die die Threads erzeugen müsste:
Delphi-Quellcode:
Hier die Unit4 mit den Threads:
procedure getbestreforgeid(reforgestringarray:treforgestringarray);
var q:integer; startstring:string; endstring:string; countarray:tcountarray; oldpoints:integer; oldresult:string; calcthread:array[0..8] of TCheckthread; threaddone:array[0..8] of boolean; threadcount:integer; btimecount:integer; label threadstartingdone; begin btimecount:=gettickcount; oldresult:='00000000000000000000000000000000'; oldpoints:=0; for q:=0 to cpucount do threaddone[q]:=true; form1.Memo2.Lines.Clear; form1.ProgressBar1.Max:=(length(reforgestringarray[0]))*(length(reforgestringarray[1]))*(length(reforgestringarray[2]))*(length(reforgestringarray[3])); form1.ProgressBar1.Position:=0; threadcount:=0; form1.label21.caption:='threads: '+inttostr(threadcount)+'/'+inttostr(cpucount); application.ProcessMessages; countarray[0]:=0; while countarray[0]<length(reforgestringarray[0]) do begin countarray[1]:=0; while countarray[1]<length(reforgestringarray[1]) do begin countarray[2]:=0; while countarray[2]<length(reforgestringarray[2]) do begin countarray[3]:=0; while countarray[3]<length(reforgestringarray[3]) do begin startstring:=''; endstring:=''; for q:=4 to 15 do countarray[q]:=0; for q:=0 to 3 do endstring:=endstring+reforgestringarray[q][countarray[q]]; for q:=4 to 15 do endstring:=endstring+reforgestringarray[q][length(reforgestringarray[q])-1]; //for q:=0 to 15 do startstring:=startstring+reforgestringarray[q][countarray[q]]; form1.Label22.Caption:=(floattostr((round((gettickcount-btimecount)/100))/10)+' seconds'); btimecount:=gettickcount; if threadcount<cpucount then begin for q:=0 to cpucount-1 do begin if threaddone[q] then begin threaddone[q]:=false; form1.memo2.lines.add('thread '+inttostr(q+1)+' of '+inttostr(cpucount)+' starting with start: '+startstring+', end: '+endstring); calcthread[q]:=tcheckthread.Create(countarray,endstring,reforgestringarray); form1.memo2.lines.add('thread started says threadhandler'); //calcthread[q].Resume; threadcount:=threadcount+1; form1.label21.caption:='threads: '+inttostr(threadcount)+'/'+inttostr(cpucount); application.ProcessMessages; Goto threadstartingdone; end; end; threadstartingdone: end; {if threadcount=cpucount then begin} {while threadcount=cpucount do begin}repeat //form1.memo2.lines.add('threadcount=cpucount2'); for q:=0 to threadcount-1 do begin //if not calcthread[q].threaddone then form1.memo2.lines.add('thread '+inttostr(q+1)+' is not done'); if calcthread[q].threaddone then begin if calcthread[q].resultpoints>oldpoints then begin oldpoints:=calcthread[q].resultpoints; oldresult:=calcthread[q].resultstring; form1.Memo2.Lines.Add('new best result: '+inttostr(oldpoints)); form1.memo2.lines.add(' str:'+oldresult); end; threadcount:=threadcount-1; form1.label21.caption:='threads: '+inttostr(threadcount)+'/'+inttostr(cpucount);; threaddone[q]:=true; calcthread[q].Free; form1.ProgressBar1.Position:=form1.ProgressBar1.Position+1; form1.Label20.Caption:=floattostr((round((form1.ProgressBar1.Position/form1.ProgressBar1.Max)*1000))/10)+' %'; form1.memo2.lines.add('thread '+inttostr(q+1)+' done'); application.ProcessMessages; end; end; sleep(500); until threadcount<>cpucount; countarray[3]:=countarray[3]+1; end; countarray[2]:=countarray[2]+1; end; countarray[1]:=countarray[1]+1; end; countarray[0]:=countarray[0]+1; end; //showmessage('ending'); while threadcount>0 do begin //form1.memo2.lines.add('threadcount=cpucount2'); for q:=0 to threadcount-1 do begin if calcthread[q].threaddone=false then form1.memo2.lines.add('thread '+inttostr(q)+' is not done'); if calcthread[q].threaddone then begin if calcthread[q].resultpoints>oldpoints then begin oldpoints:=calcthread[q].resultpoints; oldresult:=calcthread[q].resultstring; form1.Memo2.Lines.Add('new best result: '+inttostr(oldpoints)); form1.memo2.lines.add(' str:'+oldresult); end; threadcount:=threadcount-1; form1.label21.caption:='threads: '+inttostr(threadcount)+'/'+inttostr(cpucount);; threaddone[q]:=true; calcthread[q].Free; form1.ProgressBar1.Position:=form1.ProgressBar1.Position+1; form1.Label20.Caption:=floattostr((round((form1.ProgressBar1.Position/form1.ProgressBar1.Max)*1000))/10)+' %'; form1.memo2.lines.add('thread '+inttostr(q+1)+' done'); application.ProcessMessages; end; end; sleep(200); end; //showmessage('result: '+inttostr(oldpoints)+' string: '+oldresult); unit3.form3.showreforgeresult(oldresult); unit3.Form3.Visible:=true; end;
Delphi-Quellcode:
unit Unit4;
interface uses SysUtils, Classes, unit1, ExtCtrls, dialogs; //type //treforgestringarray=array[0..15] of array of string; {wowitem = record id: integer; name: string; icon: string; quality: integer; itemlvl: integer; gems: tstringlist; armor: integer; stamina: integer; intelligence: integer; strength: integer; agility: integer; hit: integer; expertise: integer; haste: integer; mastery: integer; crit:integer; dodge: integer; parry: integer; spirit: integer; end; } type TCheckThread = class(TThread) private Fstartcountarray:unit1.tcountarray; Fendstring:string; Freforgestringarray:unit1.treforgestringarray; Fthreaddone:boolean; Fresultstring:string; Fresultpoints:integer; protected function getstatname(statid:integer):string; function calcpoints(calcablestring:string):integer; procedure getbestreforgeid; procedure execute; override; public constructor Create(startcountarray:tcountarray; endstring:string; reforgestringarray:treforgestringarray); property threaddone:boolean read Fthreaddone write Fthreaddone; property resultstring:string read Fresultstring write Fresultstring; property resultpoints:integer read Fresultpoints write Fresultpoints; end; implementation constructor TCheckThread.Create(startcountarray:tcountarray; endstring:string; reforgestringarray:treforgestringarray); var i:integer; begin inherited Create(true); Fthreaddone:=false; for i:=0 to 15 do Fstartcountarray[i]:=startcountarray[i]; Fendstring:=endstring; Fresultpoints:=0; freforgestringarray:=reforgestringarray; Freeonterminate:=false; Resume; //showmessage('thread'); //self.Execute; end; function TCheckThread.getstatname(statid:integer):string; begin result:=''; if statid=1 then result:='Hit'; if statid=2 then result:='Expertise'; if statid=3 then result:='Haste'; if statid=4 then result:='Mastery'; if statid=5 then result:='Crit'; if statid=6 then result:='Dodge'; if statid=7 then result:='Parry'; if statid=8 then result:='Spirit'; end; function TCheckThread.calcpoints(calcablestring:string):integer; var calcedstats:wowitem; statvalue:integer; calcitemarray: array[0..15] of wowitem; i:integer; begin result:=0; for i:=0 to 15 do begin calcitemarray[i]:=unit1.wowitemarray[i]; statvalue:=0; if (calcablestring[2*i+1]='1')then begin statvalue:=round(calcitemarray[i].hit*0.4); calcitemarray[i].hit:=calcitemarray[i].hit-statvalue; end; if (calcablestring[2*i+1]='2')then begin statvalue:=round(calcitemarray[i].expertise*0.4); calcitemarray[i].expertise:=round(calcitemarray[i].expertise*0.6); end; if (calcablestring[2*i+1]='3')then begin statvalue:=round(calcitemarray[i].haste*0.4); calcitemarray[i].haste:=round(calcitemarray[i].haste*0.6); end; if (calcablestring[2*i+1]='4')then begin statvalue:=round(calcitemarray[i].mastery*0.4); calcitemarray[i].mastery:=round(calcitemarray[i].mastery*0.6); end; if (calcablestring[2*i+1]='5')then begin statvalue:=round(calcitemarray[i].crit*0.4); calcitemarray[i].crit:=round(calcitemarray[i].crit*0.6); end; if (calcablestring[2*i+1]='6')then begin statvalue:=round(calcitemarray[i].dodge*0.4); calcitemarray[i].dodge:=round(calcitemarray[i].dodge*0.6); end; if (calcablestring[2*i+1]='7')then begin statvalue:=round(calcitemarray[i].parry*0.4); calcitemarray[i].parry:=round(calcitemarray[i].parry*0.6); end; if (calcablestring[2*i+1]='8')then begin statvalue:=round(calcitemarray[i].spirit*0.4); calcitemarray[i].spirit:=round(calcitemarray[i].spirit*0.6); end; if (calcablestring[2*i+2]='1')then calcitemarray[i].hit:=calcitemarray[i].hit+statvalue; if (calcablestring[2*i+2]='2')then calcitemarray[i].expertise:=calcitemarray[i].expertise+statvalue; if (calcablestring[2*i+2]='3')then calcitemarray[i].haste:=calcitemarray[i].haste+statvalue; if (calcablestring[2*i+2]='4')then calcitemarray[i].mastery:=calcitemarray[i].mastery+statvalue; if (calcablestring[2*i+2]='5')then calcitemarray[i].crit:=calcitemarray[i].crit+statvalue; if (calcablestring[2*i+2]='6')then calcitemarray[i].dodge:=calcitemarray[i].dodge+statvalue; if (calcablestring[2*i+2]='7')then calcitemarray[i].parry:=calcitemarray[i].parry+statvalue; if (calcablestring[2*i+2]='8')then calcitemarray[i].spirit:=calcitemarray[i].spirit+statvalue; end; calcedstats:=extrastats; for i:=0 to 15 do begin calcedstats.hit:=calcedstats.hit+calcitemarray[i].hit; calcedstats.expertise:=calcedstats.expertise+calcitemarray[i].expertise; calcedstats.haste:=calcedstats.haste+calcitemarray[i].haste; calcedstats.mastery:=calcedstats.mastery+calcitemarray[i].mastery; calcedstats.crit:=calcedstats.crit+calcitemarray[i].crit; calcedstats.dodge:=calcedstats.dodge+calcitemarray[i].dodge; calcedstats.parry:=calcedstats.parry+calcitemarray[i].parry; calcedstats.spirit:=calcedstats.spirit+calcitemarray[i].spirit; end; if calcedstats.hit<strtoint(form1.Edit1.Text) then exit; if calcedstats.expertise<strtoint(form1.Edit2.Text) then exit; if calcedstats.haste<strtoint(form1.Edit3.Text) then exit; if calcedstats.mastery<strtoint(form1.Edit4.Text) then exit; if calcedstats.crit<strtoint(form1.Edit5.Text) then exit; if calcedstats.spirit<strtoint(form1.Edit6.Text) then exit; if calcedstats.dodge<strtoint(form1.Edit7.Text) then exit; if calcedstats.parry<strtoint(form1.Edit8.Text) then exit; if form1.ListBox1.items.IndexOf(getstatname(1))<>-1 then result:=result+calcedstats.hit*(form1.listbox1.Items.count-form1.ListBox1.Items.IndexOf(getstatname(1))); if form1.ListBox1.items.IndexOf(getstatname(2))<>-1 then result:=result+calcedstats.expertise*(form1.listbox1.Items.count-form1.ListBox1.Items.IndexOf(getstatname(2))); if form1.ListBox1.items.IndexOf(getstatname(3))<>-1 then result:=result+calcedstats.haste*(form1.listbox1.Items.count-form1.ListBox1.Items.IndexOf(getstatname(3))); if form1.ListBox1.items.IndexOf(getstatname(4))<>-1 then result:=result+calcedstats.mastery*(form1.listbox1.Items.count-form1.ListBox1.Items.IndexOf(getstatname(4))); if form1.ListBox1.items.IndexOf(getstatname(5))<>-1 then result:=result+calcedstats.crit*(form1.listbox1.Items.count-form1.ListBox1.Items.IndexOf(getstatname(5))); if form1.ListBox1.items.IndexOf(getstatname(6))<>-1 then result:=result+calcedstats.dodge*(form1.listbox1.Items.count-form1.ListBox1.Items.IndexOf(getstatname(6))); if form1.ListBox1.items.IndexOf(getstatname(7))<>-1 then result:=result+calcedstats.parry*(form1.listbox1.Items.count-form1.ListBox1.Items.IndexOf(getstatname(7))); if form1.ListBox1.items.IndexOf(getstatname(8))<>-1 then result:=result+calcedstats.spirit*(form1.listbox1.Items.count-form1.ListBox1.Items.IndexOf(getstatname(8))); //if result>28000 then showmessage(calcablestring+' result:'+inttostr(result)+' hit:'+inttostr(calcedstats.hit)+' exp:'+inttostr(calcedstats.expertise)+' haste:'+inttostr(calcedstats.haste)); end; procedure TCheckThread.getbestreforgeid; var q:integer; currentstring:string; countarray:tcountarray; points:integer; oldpoints:integer; oldresult:string; label startlabel; label endlabel; begin form1.Memo2.Lines.Add('getbestreforgeid started'); countarray:=Fstartcountarray; Goto startlabel; countarray[0]:=0; while countarray[0]<length(Freforgestringarray[0]) do begin countarray[1]:=0; while countarray[1]<length(Freforgestringarray[1]) do begin countarray[2]:=0; while countarray[2]<length(Freforgestringarray[2]) do begin countarray[3]:=0; while countarray[3]<length(Freforgestringarray[3]) do begin countarray[4]:=0; while countarray[4]<length(Freforgestringarray[4]) do begin countarray[5]:=0; while countarray[5]<length(Freforgestringarray[5]) do begin countarray[6]:=0; while countarray[6]<length(Freforgestringarray[6]) do begin countarray[7]:=0; while countarray[7]<length(Freforgestringarray[7]) do begin countarray[8]:=0; while countarray[8]<length(Freforgestringarray[8]) do begin countarray[9]:=0; while countarray[9]<length(Freforgestringarray[9]) do begin countarray[10]:=0; while countarray[10]<length(Freforgestringarray[10]) do begin countarray[11]:=0; while countarray[11]<length(Freforgestringarray[11]) do begin countarray[12]:=0; while countarray[12]<length(Freforgestringarray[12]) do begin countarray[13]:=0; while countarray[13]<length(Freforgestringarray[13]) do begin countarray[14]:=0; while countarray[14]<length(Freforgestringarray[14]) do begin countarray[15]:=0; while countarray[15]<length(Freforgestringarray[15]) do begin startlabel: currentstring:=''; for q:=0 to 15 do currentstring:=currentstring+Freforgestringarray[q][countarray[q]]; //showmessage(currentstring); //memo2.Lines.Add(currentstring); points:=calcpoints(currentstring); if points>oldpoints then begin oldpoints:=points; oldresult:=currentstring; end; if currentstring=Fendstring then Goto endlabel; form1.Memo2.Lines.Add('shortmessage'); countarray[15]:=countarray[15]+1; end; countarray[14]:=countarray[14]+1; end; countarray[13]:=countarray[13]+1; end; countarray[12]:=countarray[12]+1; end; countarray[11]:=countarray[11]+1; end; countarray[10]:=countarray[10]+1; end; countarray[9]:=countarray[9]+1; end; countarray[8]:=countarray[8]+1; end; countarray[7]:=countarray[7]+1; end; countarray[6]:=countarray[6]+1; end; countarray[5]:=countarray[5]+1; end; countarray[4]:=countarray[4]+1; end; countarray[3]:=countarray[3]+1; end; countarray[2]:=countarray[2]+1; end; countarray[1]:=countarray[1]+1; end; countarray[0]:=countarray[0]+1; end; endlabel: Fresultpoints:=oldpoints; Fresultstring:=oldresult; form1.Memo2.lines.Add('thread done says thread '+inttostr(Fresultpoints)); //showmessage('thread done says thread '+inttostr(Fresultpoints)); Fthreaddone:=true; end; procedure TCheckThread.execute; begin //Fresultpoints:=0; //showmessage('thread started '+Fendstring); getbestreforgeid; form1.Memo2.Lines.Add('thread done says thread '+inttostr(Fresultpoints)); end; end. |
AW: Thread startet execute nicht
Mein Delphi warnt, compiliert aber und hält am Breakpoint in der TCheckThread.execute-Methode an.
Code:
[DCC Warnung] Unit4.pas() H2365 Schreibweise der Überschreibe-Methode TCheckThread.execute muss exakt ihrem Vorfahren TThread.Execute entsprechen
Zitat:
Die Struktur deiner Daten scheint mir für den Anwendungsfall ungeeignet. Durch geschickte Optimierung könnte man den Ablauf sicher um den Faktor 100 beschleunigen. Das ist sinnvoller als bei diesem Entwicklungsstand bereits auf Threads zu setzen. Auf jeden Fall solltest du auf "Goto" verzichten. Ein Vorschlag ohne jetzt zu viel zu verändern:
Delphi-Quellcode:
function TCheckThread.IncCountArray(var countarray: tcountarray) : Boolean;
var n: Integer; begin for n := 15 downto 0 do begin countarray[n] := countarray[n] + 1; if countarray[n] < Length(Freforgestringarray[n]) then begin Result := True; Exit; end; countarray[n] := 0; end; Result := False; end; function TCheckThread.IsCountArrayValid(const countarray: tcountarray) : Boolean; var n: Integer; begin for n := 15 downto 0 do begin if countarray[n] >= Length(Freforgestringarray[n]) then begin Result := False; Exit; end; end; Result := True; end; procedure TCheckThread.getbestreforgeid; var q:integer; currentstring:string; countarray:tcountarray; points:integer; oldpoints:integer; oldresult:string; begin oldpoints := 0; oldresult := '00000000000000000000000000000000'; countarray := Fstartcountarray; if IsCountArrayValid(countarray) then begin repeat currentstring:=''; for q := 0 to 15 do currentstring := currentstring + Freforgestringarray[q][countarray[q]]; //showmessage(currentstring); //memo2.Lines.Add(currentstring); points := calcpoints(currentstring); if oldpoints < points then begin oldpoints := points; oldresult := currentstring; end; if currentstring=Fendstring then Break; //form1.Memo2.Lines.Add('shortmessage'); until not IncCountArray(countarray); end; //form1.Memo2.lines.Add('thread done says thread '+inttostr(Fresultpoints)); //showmessage('thread done says thread '+inttostr(Fresultpoints)); resultpoints := oldpoints; resultstring := oldresult; end; procedure TCheckThread.Execute; begin //Fresultpoints:=0; //showmessage('thread started '+Fendstring); getbestreforgeid; threaddone:=true; //form1.Memo2.Lines.Add('thread done says thread '+inttostr(Fresultpoints)); end; |
AW: Thread startet execute nicht
Zitat:
Zitat:
Zitat:
|
AW: Thread startet execute nicht
Also..
Ich habe jetzt die Unit nochmal komplett aus dem Projekt gehauen und von Delphi ein neues Thread-Objekt erzeugen lassen, dem ich meine Prozeduren wieder hinzugefügt habe. Nur leider hat es nicht geholfen. Ich habe auch probiert mal keine eigene TCheckThread.Create Prozedur zu benutzen, sondern die von TThread. Alles kein Erfolg. Mir gehen so langsam die Ideen aus. Hat keiner mehr eine Idee? |
AW: Thread startet execute nicht
Also dein Sourcecode ist noch sehr suboptimal.
Ich weiss nich ob es dir aufgefallen ist, aber dein Code besteht aus permanenten Wiederholungen. Das Ganze wird sehr unübersichtlich und da nicht mal Kommentare vorhanden sind versteht man eigentlich nur "Bahnhof". Guter Code soll aber selbsterklärend und ohne Wiederholungen sein. Hier ein kleines Beispiel:
Delphi-Quellcode:
Warum reitest du ständig auf
function TCheckThread.calcpoints(calcablestring:string):integer;
var calcedstats:wowitem; statvalue:integer; calcitemarray: array[0..15] of wowitem; i:integer; begin result:=0; for i:=0 to 15 do begin calcitemarray[i]{*}:=unit1.wowitemarray[i]; statvalue:=0; if (calcablestring[2*i+1]='1')then begin statvalue:=round(calcitemarray[i]{*}.hit*0.4); calcitemarray[i]{*}.hit:=calcitemarray[i]{*}.hit-statvalue; end;
Delphi-Quellcode:
herum?
calcitemarray[i]
Verwendet eine einfache lokale Variable
Delphi-Quellcode:
und die Sache wird schon klarer.
var item:wowitem;
Du verwendest 16 Mal den Ausdruck
Delphi-Quellcode:
; das tut doch in den Augen weh.
calcablestring[2*i+1]
Auch hier: verwende eine lokale Zwischenvariable (Datentyp char)! Deine Funktion/Methoden sind elendlang; sie passen nicht auf eine Seite und man muss ständig hoch und runterscrollen. Halte deine Funktionen kurz und verwende Unterfunktionen! Wenn du diese beiden Regeln beachtest kannst du deinen Code deutlich verbessern. |
AW: Thread startet execute nicht
Also ich finde es ja sehr hilfreich, dass ihr versucht mir zu helfen, meinen Code zu verbessern, aber ich würde gerne erst einmal Alles zum laufen zu bringen, bevor ich zu optimieren beginne. Würde es euch denn helfen mein aktuelles Problem zu lösen, wenn ich meinen Code auskommentiere etc.?
|
AW: Thread startet execute nicht
Da du sagst, das Execute wird gar nicht ausgeführt, kannst du den Code darin auch weglassen bzw. auf eine Art Platzhalter reduzieren. Damit fällt schon mal ein großer Verwirrfaktor raus.
|
AW: Thread startet execute nicht
Zitat:
Dein Code sieht z.Zt. so aus ![]() Ein falscher Draht und nix funktioniert. Wie soll man so ein Wirrwarr zum laufen bringen? Du darfst z.B. aus einem Thread heraus nicht direkt auf ein Formular zugreifen weil die VCL nicht threadsicher ist. In deinem Code passiert das aber dutzende Male. |
AW: Thread startet execute nicht
Wenn ich die TCheckthread.execute komplett raus kommentiere, dann bekomme ich eine EAbstractError Exception. Nehme ich den Code wieder rein, dann wird er nicht ausgeführt.
Im übrigen funktioniert es auch nicht, wenn ich sämtliche Zugriffe auf Formular 1 entferne. Ich weis aber auch, dass der Code in der TCheckthread.execute funktioniert, weil wenn ich diese Prozedur von Unit 1 ausführe, dann wird es zwar nicht als Thread ausgeführt, aber ich komme zu meinem Ergebnis. Edit: Übrigens kann man das Bild nicht sehen @sx2008 |
AW: Thread startet execute nicht
Was genau bringt dich denn zu dem Schluss, daß Execute nicht ausgeführt wird?
|
AW: Thread startet execute nicht
Ich habe versucht über showmessage und über ein memo auf Form1 eine Nachricht anzuzeigen. Beides kommt nicht zu stande.
Mir ist aber dabei was Interessantes aufgefallen. Wenn ich den Code ändere, dann wird die execute in einigen, nicht einfach reproduzierbaren Fällen ausgeführt. |
AW: Thread startet execute nicht
Ein Zugriff aus dem Thread Kontext auf die VCL oder auch ShowMessage ist ein absolutes NoGo.
Sowas nur synchronisiert machen. Zum Thema Threads solltest du dir ein paar Tutorials ansehen, denn das ist nicht trivial. |
AW: Thread startet execute nicht
Ich habe mir schon einige durchgelesen, jedoch wüsste ich nicht, wie mir das Synchroniesieren hier helfen sollte. Und soo schwer sind Threads mit TThread ja nun auch nicht.. naja.. also wenn es denn dann funktioniert :?
|
AW: Thread startet execute nicht
Zitat:
|
AW: Thread startet execute nicht
Zitat:
Es ist hier schon mehrfach deutlich gemacht worden, daß Zugriffe auf die VCL (dazu gehört Showmessage und das Manipulieren eines Memos) aus einem Thread heraus nur eingeschränkt, wenn überhaupt, funktionieren. Deine Beobachtungen bestätigen das doch sehr anschaulich. Wenn dir also schon mehrere Leute sagen, was du falsch machst, dann halte dich doch bitte zunächst mal an diese gut gemeinten Ratschläge! |
AW: Thread startet execute nicht
Ok, ich denke ich habe nun verstanden, was mein Fehler ist. Ich habe einfach mal über die execute Prozedur eine synchronisierte Prozedur gestartet, die mir eine Nachricht anzeigt. Das heist, dass die execute doch gestartet wird. Ich hatte einfach die Auswirkung unterschätzt, die entsteht, wenn man etwas unsynchronisiert anzeigen möchte. Demzufolge wäre dann eine andere Threadüberschrift wirklich hilfreich gewesen, ich bin aber davon ausgegangen, dass die execute einfach nicht gestartet wird. Im Ergebnis muss ich also meinen Fehler im Quellcode des Threads suchen.
Eine andere Frage, die bei mir da grade so aufkommt, ist noch: Warum akzeptiert
Delphi-Quellcode:
keine Prozeduren mit Parametern?
synchronize()
|
AW: Thread startet execute nicht
Weil TThreadMethod eine parameterlose Methode ist. Du kannst aber doch eine solche synchronisieren, innerhalb derer Du dann einfach eine Methode mit Parametern aufrufst.
[edit] Vielleicht war das jetzt etwas schwer verständlich, daher ein Beispiel:
Delphi-Quellcode:
[/edit]
...
Synchronize(Parameterlos); ... procedure TDeinThread.Parameterlos; begin MachIrgendwas(FPrivatesFeld1, FPrivatesFeld2); end; procedure TDeinThread.MachIrgendwas(Param1, Param2: integer); begin //Code end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:50 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