Entwickler-Ecke

Sonstiges (Delphi) - Anwendung warten lassen bis alle Threads terminieren


mk3 - Mi 08.10.03 10:33
Titel: Anwendung warten lassen bis alle Threads terminieren
Hallo alle zusammen,

ich will die Mailversand in 3 Threads starten und mein Programm warten lassen, bis alle Terminieren. Aber wie mache ich es? Die Code sieht vereinfacht 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:
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:
// deklaration von Threads
ThreadArray: array of TVersandThreads;
AnzahlThreads : integer;

// Versand-funktion
function TOutlookOutput.Versende: boolean;
var
  i:integer;
begin
  AnzahlThreads:= 3;
  Setlength(ThreadArray, AnzahlThreads);
  // in einer Schleife die Threads erzeugen
  for i := 0 to length(ThreadArray) - 1 do begin
    ThreadArray[i] := TVersandThreads.Create(true);
    ThreadArray[i].FMsgStore := FMsgStore;
    ThreadArray[i].FreeOnTerminate := True;
    ThreadArray[i].OnTerminate := ThreadDone;
    ThreadArray[i].Resume;
  end

  // Diese Funktion soll True zurückmelden wenn alle Threads Terminieren.
  // Das heisst, dass Versand beendet ist!
  ???
end;  

procedure TOutlookOutput.ThreadDone(Sender: TObject);
var i : integer;
begin
  Dec(AnzahlThreads);
  ???
End;

// jetzt Thread
type
  TVersandThreads = class(TThread)
  private
    procedure DoSomething;
   function SetMessageProps(Message: TRwMapiMessage): boolean;    
  protected
    procedure Execute; override;
  public
    FmsgStore : TrwMapiMsgStore;
end;

implementation

procedure TVersandThreads.Execute;
begin
    DoSomething();
end;

procedure TVersandThreads.DoSomething;
var
  NewMessage: TRwMapiMessage;
  Outbox : TRwMapiFolder;
Begin
   Outbox := FMsgStore.OpenFolder(ftOutbox, alReadWrite);
   NewMessage:= OutBox.CreateMessage;
   SetMessageProps(NewMessage);
   NewMessage.SubmitMessage(asMoveToSentItems, false);
   NewMessage.Free;  
end;



ich habe in der Function ThreadDone eine Variable Erfolgreich auf True gesetzt, wenn AnzahlThreads = 0 und in der function Versende in while-Schleife den Wert von Erfolgreich abgefragt, aber die Anwendung hängt.

Danke sehr für jede Hilfe und jeden Hinweis!
mk

Moderiert von user profile iconKalabutermann: Code- in Delphi-Tags geändert.


Delete - Mi 08.10.03 10:53

WaitForMultipleObjects
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/waitformultipleobjects.asp


MSCH - Mi 08.10.03 12:02

Schau dir mal die Hilfe zu SetEvent an.
grez
msch


mk3 - Mi 08.10.03 15:11

Danke für die Antworten, aber es hilft mir leider nicht weiter. Ich habe mit der folgenden Code versucht:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
ThreadHandles : array of THANDLE; 

function TOutlookOutput.Execute: boolean;
   ...
    for i:= 0 to length(ThreadArray) - 1 do begin
      // Thread erstellen
      ...
      ThreadHandles[i] := ThreadArray[i].Handle;
      ...
      ThreadArray[i].Resume; 
    end;      

   WaitForMultipleObjects(AnzahlThreads, @ThreadHandles,   
                                     true, 1000);
end;

Wie ich verstanden habe, hilft WaitForMultipleObjects für die Synchronisation.

Ich brauche an der Stelle aber keine Synchronisationsmechanismen. Ich will dass meine Funktion, wo ich Threads erzeuge nur dann einen Wert(true oder false) zurückgibt, wenn alle Threads seine Arbeit zu ende gemacht haben. Also, die Anwendung soll warten, bis alle erzeugte Threads terminieren. Wie mache ich es? Kann mir jemand helfen? :cry:

Danke sehr
mk

Moderiert von user profile iconTino: Code- durch Delphi-Tags ersetzt.


MSCH - Mi 08.10.03 15:37

Wie gesagt, schau dir SetEvent an. Ganz grob; jeder Thread erhöht eine Globale Variable wenn er gestartet wurde und erniedrigt diese, wenn er beendet wurde. Der Letzte Thread gibt ein Event an die Anwendung, dass alles beendet wurde.
Die Variable muss übrigens threadsicher deklariert werden.

Suche in: Delphi-Forum, Delphi-Library WAITFORSINGLEOBJEKT ist hier ganz falsch, wenn ich auf einen Thread warten muss, kann ich den ganzen Code gleich in die Anwendung schreiben, welchen Vorteil hat es sonst Code auszulagern und dann doch zu warten? (Ausnahmen bestätigen die Regel)

grez
msch


Motzi - Mi 08.10.03 21:31

Und wieso nicht Suche in: Delphi-Forum, Delphi-Library WAITFORMULTIPLEOBJECTS ??

Delphi-Quelltext
1:
2:
while WaitForMultipleObjects(<count>, <HandleArray>, True, 100) = WAIT_TIMEOUT do
  Application.ProcessMessages;


Wartet bis alle Threads beendet sind und arbeitet zwischendurch immer wieder die Message-Queue ab, damit der Main-Thread nicht "einfriert"...