Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Definition Funktion um Threads zu befüllen (https://www.delphipraxis.net/184037-definition-funktion-um-threads-zu-befuellen.html)

SyntaxXx 20. Feb 2015 19:29

Definition Funktion um Threads zu befüllen
 
Guten Abend zusammen,
ich bin gerade dabei, eine multithreaded Anwendung zu schreiben.

Dazu erstelle ich eine bestimmte Anzahl an Workerthreads, welche so lange arbeiten, bis es nichts mehr gibt.
Jetzt brauche ich aber eine Funktion, die die einzelnen Threads mit Werten versorgt.
Doch wo definiere ich diese Funktion?

Wenn ich die in der Threadklasse anlege und z.B. 5 Threads anlege, dann gibt es natürlich diese Methode auch 5 mal und jeder Thread würde alles abarbeiten.
Daher überlege ich, diese Funktion in der TForm Klasse zu definieren.
Doch dann müsste ich aus den Threads raus die Funktion so aufrufen: MeinWert := TForm1.MeineFunktion;

Doch macht man das so oder gibt es da nicht eine bessere Lösung?

Sir Rufo 20. Feb 2015 19:39

AW: Definition Funktion um Threads zu befüllen
 
Du hast doch XE4 und dort hast du auch die anonymen Methoden

Schreibe einfach eine anonyme Methode und reiche die an den ThreadPool. Der gibt diese dann an einen freien Worker und der führt diese dann aus.

Wenn du diese anonyme Methode jetzt noch in ein (oder eher 2) Interface bettest, dann wird alles schön :)

SyntaxXx 20. Feb 2015 20:17

AW: Definition Funktion um Threads zu befüllen
 
Mir fällt da gerade ein, die Threadklasse hat doch auch die Synchronize Methode.
Das würde mir ja eigentlich schon reichen.

Nur scheint man damit keine anonyme Funktionen aufrufen zu können.

Delphi-Quellcode:
MeinString := TThread1.Synchronize(
      function : String
      begin
        result := 'Nur ein Test';
      end
    );

Medium 20. Feb 2015 21:51

AW: Definition Funktion um Threads zu befüllen
 
Lies mal die Hilfe zu TThread.Synchronize(). Was du vor hast, macht man in der Regel mit CriticalSections, und wessen Member die versorgende Methode letztlich ist, hängt davon nicht ab. CriticalSections stellen sicher, dass zwei Threads (in deinem Fall Mainthread und dein Workerthread) Code nicht gleichzeitig ausführen können, der zwischen dem Einstieg und dem Ausstieg aus der CriticalSection steht. Genutzt wird soetwas zum Beispiel, wenn ein Thread eine Liste eines anderen befüllt. Sowohl der schreibende als auch der lesende Zugriff müssen dabei dann gegeneinander verriegelt werden. Pseudocode:
Delphi-Quellcode:
// Workerthread
procedure TWorkerThread.Execute;
begin
  while not Terminated do
  begin
    if not List.IsEmpty then
    begin
      MyCriticalSection.Enter;
      try
        DoSomethingWith(List[0]);
        List.Delete(0);
      finally
        MyCriticalSection.Leave;
      end;
    end;
  end;
end;

procedure TWorkerThread.AddListItem(aListItem: TListItem);
begin
  MyCriticalSection.Enter;
  try
    List.Add(aListItem);
  finally
    MyCriticalSection.Leave;
  end;
end;

// Hauptthread
procedure TForm1.OnButton1Click(Sender: TObject);
begin
  WorkerThread.AddListItem(TListItem.Create(foo, bar));
end;

himitsu 21. Feb 2015 00:17

AW: Definition Funktion um Threads zu befüllen
 
Zitat:

Zitat von SyntaxXx (Beitrag 1290807)
Nur scheint man damit keine anonyme Funktionen aufrufen zu können.

Doch kann man, aber wenn man die Dokumentation nicht oder nicht richtig liest, dann ...

Denn man kann nur parameterlose und vorallem rückgabewertlose vordefinierte Synchronize-Methoden ausrufen, so wie das schon immer war.
Und man muß natürlich auch beachten was man alles als Parameter übergeben muß.

Delphi-Quellcode:
TThread.Synchronize(nil, procedure
  begin
    MeinString := 'Nur ein Test';
  end);

TThread.Synchronize(Thread1, procedure
  begin
    MeinString := 'Nur ein Test';
  end);

{T}Thread1.Synchronize(procedure
  begin
    MeinString := 'Nur ein Test';
  end);

...

@Medium: Natürlich müsste doch jeder Zugriff auf List in die CS rein, also auch das
Delphi-Quellcode:
if not List.IsEmpty then
.
Und bezüglich der sinnlosen CPU-Auslastung könnte/sollte man das Ganze noch um Events erweitern.

Medium 22. Feb 2015 07:24

AW: Definition Funktion um Threads zu befüllen
 
Das ist eine Illustration, eine Skizze. Deswegen ja Pseudocode. Bei dem IsEmpty hast du allerdings Recht, der ist mir durch die Lappen gegangen. (Generell wäre es an sich geschickter eine Threadsafe-Liste von TList o.ä. abzuleiten und dort die Criticalsection unterzubringen, sowie alle Zugriffsmethoden dahingehend zu erweitern. Aber das wäre hier doch etwas lang geworden.) Und statt Events tut's in so einfachen Fällen auch ein Sleep(1) in der Schleife. Nicht Best-Practice, aber ich habe noch keine wirklich gute technische Gegenargumente dazu gesehen.

Dejan Vu 22. Feb 2015 08:04

AW: Definition Funktion um Threads zu befüllen
 
Natürlich nur eine Skizze, trotzdem kann man verbessern:
Zitat:

Zitat von Medium (Beitrag 1290811)
Pseudocode:
Delphi-Quellcode:
// Workerthread
procedure TWorkerThread.Execute;
begin
...
      MyCriticalSection.Enter;
      try
        DoSomethingWith(List[0]);
        List.Delete(0);
      finally
        MyCriticalSection.Leave;
      end;
...

Hupsa: Solange ein Job ausgeführt wird, ist die Liste bzw. der Zugriff auf Selbige blockiert. besser so:
Delphi-Quellcode:
// Workerthread
procedure TWorkerThread.Execute;

  Function NextItemInList : ISomethingToDo;
  begin
    MyCriticalSection.Enter;
      try
        If List.Count>0 then begin
          Result := List[0];
          List.Delete(0);
        else Result := nil;
      finally
        MyCriticalSection.Leave;
      end;
  end;

begin
...
      DoSomethingWith(NextItemInList);
...
Jetzt ist nur das Extrahieren des ersten Elements der Jobliste exklusiv. 'DoSomethingWith' sollte nun noch prüfen, ob der übergebene Job <> nil ist.
Ich würde zudem noch eine Semaphore einführen und den Thread schlafen legen. Das 'AddItem' weckt ihn auf, indem die Semaphore per 'ReleaseSemaphore' um 1 erhöht wird. Damit rennt die Execute-Methode automatisch so lange, wie Jobs in der Liste sind.

Siehe auch:
http://www.delphipraxis.net/93835-wo...ntergrund.html


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:40 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