Autor Beitrag
walter_b
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 135

Windows Vista/XP
Delphi 6
BeitragVerfasst: 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):

ausblenden volle Höhe 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:
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
    { Private-Deklarationen }
   MyThread: TThread;
  public
    { Public-Deklarationen }
  end;

  TMyThread = class(TThread)
  protected
    procedure Execute; override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TMyThread }

procedure TMyThread.Execute;
begin
  while not Terminated do
  begin
    MessageBeep(UINT(-1));
    Sleep(1000);
  end;
end;

{ TForm1 }

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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 481

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Sa 26.07.08 12:21 
Arbeite am Besten mal das Tutorial zu Threads von user profile iconLuckie durch. ;-)

_________________
We are, we were and will not be.
walter_b Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 135

Windows Vista/XP
Delphi 6
BeitragVerfasst: Sa 26.07.08 12:46 
Ich habe das Tutorial nochmal durchgelesen und für mich etwas erstellt, was soweit auch funktioniert:

ausblenden volle Höhe 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:
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);
  // Warten, bis es fertig ist.

  writeln('hallo');
end;



[...]

//Hauptprogramm
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 135

Windows Vista/XP
Delphi 6
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic starofftopic star
Beiträge: 1098
Erhaltene Danke: 13

Win7 geg. WInXP oder sogar Win98
Rad2007
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: Mo 28.07.08 11:07 
user profile iconwalter_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 user profile iconTilo ja schon geschrieben.
walter_b Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 135

Windows Vista/XP
Delphi 6
BeitragVerfasst: 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

ausblenden 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
ontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic starofftopic star
Beiträge: 1098
Erhaltene Danke: 13

Win7 geg. WInXP oder sogar Win98
Rad2007
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 135

Windows Vista/XP
Delphi 6
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic starofftopic star
Beiträge: 1098
Erhaltene Danke: 13

Win7 geg. WInXP oder sogar Win98
Rad2007
BeitragVerfasst: Mo 28.07.08 20:30 
Hast Du dem Array auch Speicher zugewiesen?
z.B. mit setlength()?

ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 135

Windows Vista/XP
Delphi 6
BeitragVerfasst: Mo 28.07.08 23:07 
Jep, der Array wurde festgelegt. Der String ebenfalls.
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: 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