Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Probleme mit Thread Synchronisierung
sPeeD2k5 - Do 16.07.09 08:03
Titel: Probleme mit Thread Synchronisierung
So nachdem ich mir einige grundlegende Tutorials angeschaut habe, habe ich versuch meinen Portscanner threadfähig zu machen. Das ganze funktioniert auch solange ich nichts speichern will, wofür ich ja die Synchronisation brauche. Allerdings haut die nicht so recht hin, obwohl ich einen kritischen Abschnitt eingebaut habe, wo ja andere Threads nicht drauf zugreifen können, wenn einer Thread gerade in diesem Bereich ist.. ALlerdings bekomm ich immernoch Zugriffsverletzungen und weiß nicht so recht warum, hoffe ihr könnt mir helfen.
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: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101:
| unit UThread;
interface
uses Classes, dialogs, sysutils, uScanner, SyncObjs; type TBinFertig = procedure(const Content: String) of object;
myThread = class(TThread)
private FBinFertig: TBinFertig; FBufferCritSect: TCriticalSection; procedure SyncBinFertig; protected procedure Execute; override; public property BinFertig: TBinFertig read FBinFertig write FBinFertig; procedure FormCreate(Sender: TObject); end;
var i :integer = 0; result1 : string; kritischerAbschnitt: TCriticalSection;
implementation
procedure mythread.FormCreate(Sender: TObject);
begin kritischerAbschnitt :=TCriticalSection.Create; end;
procedure mythread.SyncBinFertig; var blub :tstringlist; begin FBufferCritSect.Enter; blub := tstringlist.Create; blub.LoadFromFile('blub.txt'); blub.Add(result1); blub.SaveToFile('blub.txt'); FBufferCritSect.Leave;
end;
procedure mythread.Execute; var result :string; blub : tstringlist; begin try randomize;
if scantcpport('127.0.0.1',21+i) = true then begin result1 := 'port '+inttostr(21+i)+' offen';
end else begin result1 := 'port '+inttostr(21+i)+' closed';
end;
inc(i); terminate; Synchronize(SyncBinFertig); finally
end; end;
end. |
Xentar - Do 16.07.09 08:41
Du hast deine CriticalSection als Private Variable - da bringt sie nichts, weil ja jeder Thread eine eigene erzeugt.
Critical Sections müssen immer global erreichbar sein, und darf es somit auch nur einmal geben.
Du hast zwar eine globale - diese wird aber bei jedem Thread Create überschrieben, und außerdem nie verwendet.
Sonstiges:
a) Schau dir mal an, was ein Constructor ist
b) Du gibst deine Stringliste nicht frei. Schau dir noch try ... finally an
c) im execute: ein try..finally Block, wobei finally leer ist macht wenig Sinn.
Edit:
d) Gewöhn dir den Vergleich auf = true direkt wieder ab
e) Du greifst von mehreren Threads aus auf die Variable i zu. Selbst das kann, ohne Synchronisierung, schon zu komischen Effekten führen.
sPeeD2k5 - Do 16.07.09 08:54
So hab jetzt mal kleine Veränderungen vorgenommen und es scheint zu funktionieren... hab ich trotzdem noch irgndwo etwas übersehen?
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: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116:
| unit UThread;
interface
uses Classes, dialogs, sysutils, uScanner, SyncObjs; type TBinFertig = procedure(const Content: String) of object;
myThread = class(TThread)
private FBinFertig: TBinFertig;
procedure SyncBinFertig; protected procedure Execute; override; public kritischerAbschnitt: TCriticalSection; property BinFertig: TBinFertig read FBinFertig write FBinFertig; procedure FormCreate(Sender: TObject); constructor Create; end;
var i :integer = 0; result1 : string;
implementation
constructor mythread.Create; begin inherited Create(true); kritischerAbschnitt :=TCriticalSection.Create; end;
procedure mythread.FormCreate(Sender: TObject);
begin end;
procedure mythread.SyncBinFertig; var blub :tstringlist; begin kritischerabschnitt.Enter; try blub := tstringlist.Create; blub.LoadFromFile('blub.txt'); blub.Add(result1); blub.SaveToFile('blub.txt'); finally blub.free; kritischerabschnitt.Leave; end;
end;
procedure mythread.Execute; var result :string; blub : tstringlist; begin try randomize;
if scantcpport('127.0.0.1',21) = true then begin result1 := 'port '+inttostr(21)+' offen';
end else begin result1 := 'port '+inttostr(21)+' closed';
end;
finally terminate; Synchronize(SyncBinFertig); end; end;
end. |
Xentar - Do 16.07.09 09:03
Du erzeugst immer noch für JEDEN Thread eine eigene CS. So macht das Ding keinen Sinn.
Nimm eine globale, erzeug diese z.b. im Aufrufenden Formular, und verwende Sie dann nur noch in den Threads.
Nochmal sonstiges:
- Relative Dateipfade sind böse
- Execute: Wieso das terminate? Der Thread ist doch danach eh zu Ende.
- Execute: Im finally Block noch die Speichern Prozedur aufzurufen halte ich für... gewagt.
sPeeD2k5 - Do 16.07.09 09:19
wie soll ich die im aufrufenden Forumal erzeugen? Wenn ich in diesem Formular
Delphi-Quelltext
1:
| thread.kritischerAbschnitt := TCriticalSection.Create; |
sagt er mir nur dass er TCriticalSection nicht kennt...
Xentar - Do 16.07.09 09:23
Bind die entsprechende Unit ein.
Aber wieso schon wieder "thread.kritischerAbschnitt" ?
sPeeD2k5 - Do 16.07.09 09:37
sorry mein fehler...
Hab übersehen, dass man die Syncobjs einbinden muss ;) In dem aufrufenden Forumular habe ich jetzt folgendes zu stehn:
Delphi-Quelltext
1: 2: 3:
| kritischerAbschnitt := TCriticalSection.Create; thread := mythread.Create; thread.FreeOnTerminate := True; |
das mit den relativen Pfaden ist mir durchaus bewusst, es war lediglich ein flüchtigkeitsfehler, da ich nur eben testen wollte, ob er etwas in die Datei schreibt ;)
Ist sonst noch etwas zu beachten?
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!