| Autor |
Beitrag |
walter_b
      
Beiträge: 135
Windows Vista/XP
Delphi 6
|
Verfasst: Sa 26.07.08 12:08
Hallo Leute
Ich würde gerne aus einem normalen Programm ein Multithread-Programm machen. Das Problem ist jetzt nur, dass ich nicht so recht mit dem Thread zu Gange komme. Ich habe schon in der Hilfe gelesen und auch sonst Sachen angeguckt, aber irgendwie funktioniert das bei mir nicht so recht.
Zuerst einmal: Welche Uses sind notwendig dafür? Reicht Classes?
Hier habe ich mal ein Codesample aus einem etwas älteren Posting von Sprint ( www.delphi-forum.de/....php?p=230946#230946):
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:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private MyThread: TThread; public end;
TMyThread = class(TThread) protected procedure Execute; override; end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TMyThread.Execute; begin while not Terminated do begin MessageBeep(UINT(-1)); Sleep(1000); end; end;
procedure TForm1.Button1Click(Sender: TObject); begin if not Assigned(MyThread) then begin MyThread := TMyThread.Create(True); with MyThread do begin FreeOnTerminate := True; Resume; end; end; end;
procedure TForm1.Button2Click(Sender: TObject); begin if Assigned(MyThread) then MyThread.Terminate; end;
end. |
Von der Struktur her sieht für mich das alles ganz Interessant aus, da es relativ einfach ist. Aus diesem Grund habe ich es auch so versucht, nachzubauen, allerdings kommt bei mir immer das Problem, dass ich in einer Konsolenapplikation arbeite und folglich am Anfang die Deklaration mit dem TForm nicht stimmt. Allerdings weiss ich nicht, wie ich den Thread jetzt umdeklarieren muss, sodass es bei mir funktioniert. Wäre euch dankbar, wenn mir jemand ein einfaches Beispiel machen könnte, um dies zu veranschaulichen.
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 481
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Sa 26.07.08 12:21
Arbeite am Besten mal das Tutorial zu Threads von Luckie durch. 
_________________ We are, we were and will not be.
|
|
walter_b 
      
Beiträge: 135
Windows Vista/XP
Delphi 6
|
Verfasst: Sa 26.07.08 12:46
Ich habe das Tutorial nochmal durchgelesen und für mich etwas erstellt, was soweit auch funktioniert:
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:
| type TThreadFunc1 = function(Parameter: Pointer): Integer; TThreadFunc2 = function(Parameter: Pointer): Integer; TThreadFunc3 = function(Parameter: Pointer): Integer; TThreadFunc4 = function(Parameter: Pointer): Integer;
function ThreadFunc1(tp: Integer): Integer; var I:integer; begin for I:=0 to 100 do Writeln('tschau'); end;
function ThreadFunc2(tp: Integer): Integer; var I:integer; begin for I:=0 to 100 do Writeln('bye'); end;
function ThreadFunc3(tp: Integer): Integer; var I:integer; begin for I:=0 to 100 do Writeln('cya'); end;
function ThreadFunc4(tp: Integer): Integer; var I:integer; begin for I:=0 to 100 do Writeln('buybuy'); end;
procedure RunThread; var tp : Integer; Thread : THandle; ThreadID : Cardinal; ExitCode : Cardinal; begin Thread := BeginThread(nil, 0, @ThreadFunc1, 0, 0, ThreadID); Thread := BeginThread(nil, 0, @ThreadFunc2, 0, 0, ThreadID); Thread := BeginThread(nil, 0, @ThreadFunc3, 0, 0, ThreadID); Thread := BeginThread(nil, 0, @ThreadFunc4, 0, 0, ThreadID); writeln('hallo'); end;
[...]
begin RunThread; end. |
Hier funktioniert es soweit, nur weiss ich nicht, wie ich das mit dem Warten anstellen soll, dass auch gewartet wird, bis der Thread fertig ist. Mit ThreadFunc4.WaitFor meldet er "not enough actual Parameters". Und wenn ich die Funktion aus dem Tutorial nehme (WaitForSingleObject(Thread, INFINITE); ), dann meldet er mir "undeclared identifier "WaitforSingleObject. Wo liegt der Hund begraben?
|
|
walter_b 
      
Beiträge: 135
Windows Vista/XP
Delphi 6
|
Verfasst: So 27.07.08 18:24
Alles funktioniert soweit, nur habe ich noch ein letztes Problem. Bei mir laufen im Moment 4 Threads parallel und alle kommen ziemlich zeitgleich zu einem Ende. Jedoch möchte ich jetzt, falls in einem bestimmten Thread gewisse Gegebenheiten gegeben sind, alle 4 beendet werden. EndThread funktioniert bei mir irgendwie nur auf denjenigen, in welchem ich es schreibe. Kann mir jemand weiterhelfen? Wie kann ich die 4 beenden? Das Programm sollte jedoch noch nicht ganz beendet werden, sondern nur diese Threads.
|
|
Tilo
      
Beiträge: 1098
Erhaltene Danke: 13
Win7 geg. WInXP oder sogar Win98
Rad2007
|
Verfasst: Mo 28.07.08 08:08
TThread.Terminate setzt eine boolsche Variable(->Terminated oder so). Diese Variable brauchst Du im betreffenden Thread nur regelmäßig abfragen. Ist die Variable gesetzt (->True) dann beende den Thread.
|
|
Yogu
      
Beiträge: 2598
Erhaltene Danke: 156
Ubuntu 13.04, Win 7
C# (VS 2013)
|
Verfasst: Mo 28.07.08 11:07
walter_b, deine Variante mag ja auch funktionieren, aber wir arbeiten hier mit Delphi, und deshalb ist objektorientierte Programmierung vorzuziehen.
Über Datei > Neu > Thread erstellt Delphi dir ein Grundgerüst eines Threads. Das kannst du jetzt ausbauen, deine eigenen Wünsche einbauen. Wie man einen solchen Thread beendet, hat Tilo ja schon geschrieben.
|
|
walter_b 
      
Beiträge: 135
Windows Vista/XP
Delphi 6
|
Verfasst: Mo 28.07.08 14:25
Mich hauts jetzt dann gleich aus den Socken... Wenn ich im Thread etwas in einen String speichern will, kommt immer ein Error: "... raised Exeption class EAccessViolation with message 'Access violation at address ...".
z.b. bei dieser Stelle
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| var s: string; a: array of byte;
begin a[0]:=33; s[1]:=Chr(a[0]); end; |
Ich raffs nicht. Wenn ich das genau gleich ausserhalb des Threads mache, funktioniert es, innerhalb jedoch nicht. Warum das?
|
|
Tilo
      
Beiträge: 1098
Erhaltene Danke: 13
Win7 geg. WInXP oder sogar Win98
Rad2007
|
Verfasst: Mo 28.07.08 17:24
Ist das ThreadObjekt zu diesem Zeitpunkt schon initialisiert?
Wie greifst Du auf den String zu(Über eine Methode des Threads oder der Haupt-Unit)?
|
|
walter_b 
      
Beiträge: 135
Windows Vista/XP
Delphi 6
|
Verfasst: Mo 28.07.08 17:53
Ja, das ThreadObjekt ist initialisiert und wird zu dem Zeitpunkt auch ausgeführt. Auf den String greife ich nur in dem Thread zu, da der String auch nur in dem Thread als lokale Variable definiert ist.
|
|
Tilo
      
Beiträge: 1098
Erhaltene Danke: 13
Win7 geg. WInXP oder sogar Win98
Rad2007
|
Verfasst: Mo 28.07.08 20:30
Hast Du dem Array auch Speicher zugewiesen?
z.B. mit setlength()?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| var s: string; a: array of byte;
begin setlength(a,1); a[0]:=33; s[1]:=Chr(a[0]); end; |
|
|
walter_b 
      
Beiträge: 135
Windows Vista/XP
Delphi 6
|
Verfasst: Mo 28.07.08 23:07
Jep, der Array wurde festgelegt. Der String ebenfalls.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 28.07.08 23:22
Für die, die es interessiert, hier wurde ihm schon eine Lösung genannt:
www.delphipraxis.net...+einmal+beenden.html
|
|