Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi x Threads die gemeinsam eine Task-Liste abarbeiten, wie?? (https://www.delphipraxis.net/85198-x-threads-die-gemeinsam-eine-task-liste-abarbeiten-wie.html)

7down 27. Jan 2007 08:53


x Threads die gemeinsam eine Task-Liste abarbeiten, wie??
 
Hallo alle zusammen!

Sagen wir ich habe eine Liste in der jede Zeile einem Job entspricht.
Die Jobs haben alle das selbe Muster, soll heißen, es geht nur um Datei-Uploads.
In der Liste stehen die einzelnen Pfade zu den Files die hochgeladen werden sollen.

Jetzt brauche ich sagen wir 10 Threads. Angenommen in der Liste sind über 10 Jobs, dann sollen sich die 10 Threads jeweils einen Job nehmen und ihn abarbeiten. Wenn Sie fertig sind sollen sie gucken, ob noch Jobs in der Liste sind, wenn ja -> weitermachen, wenn nicht, warten bis wieder was reinkommt.

Mich würde mal interessieren wie man sowas grundsätzlich löst.
Mit Threads an sich kenne ich mich eigenlich relativ gut aus inzwischen.

Wär super wenn jemand ein paar Codeschnipsel oder so hätte, oder eine Erklärung sollte es auch tun.

Vielen Dank schon mal!!

Gruß
7down

MrKnogge 27. Jan 2007 09:27

Re: x Threads die gemeinsam eine Task-Liste abarbeiten, wie?
 
Moin,
ich versstehe jetzt deine Frage / dein Problem nicht ganz. Sobald die Datei fertig hochgeladen ist, überprüfst du ob es noch Jobs gibt, falls ja liest liest du wieder einen aus deiner Liste.

Um zu erkennen, ob ein Job von einem Thread bereits bearbeitet wird, kannst du ja die Eigenschaft Tag auf 1 setzen
(z.B. Tag = 0 => ist noch zu bearbeiten, Tag = 1 wird gerade bearbeitet)

Um darauf zu reagieren, wenn neue Aufträge deiner Liste hinzugefügt werden, so kanst du entweder die Threads von dort starten
wo du auch die Aufgaben der Liste hinzufügst, oder du nimmst das OnChange-Erreigniss deiner Listbox.

Gruß

alzaimar 27. Jan 2007 09:29

Re: x Threads die gemeinsam eine Task-Liste abarbeiten, wie?
 
Entweder Du implementierst ....
...eine threadsichere Liste, aus der sich die Threads bedienen, oder
...eine Jobliste, die die Jobs in ihrer Execute-Methode an wartende Threads eines Threadpools verteilt.

Ich würde die zweite Variante nehmen. Die 'Add'-Methode der TJoblist fügt den Job in eine Liste ein und erhöht einen threadsicheren Zähler (Semaphore). Die Execute-Methode wartet auf die Semaphore und verteilt das erste Element (LIFO-Prinzip) auf den nächsten freien Thread.

Delphi-Quellcode:
Procedure TJobList.AddJob (aJob : TJob);
Var
  L : TList;

Begin
  L := fJobList.LockList;
  Try
    L.Add (aJob);
    ReleaseSemaphore (fSemaphore,1,nil); // Oder so ähnlich
  Finally
    fJobList.UnlockList;
  End;
End;

Procedure TJobList.Execute;
Var
  L : TList;
  nextJob : TJob;

Begin
  While not Terminated do
    If WaitForSingleObject (fSemaphore,INFINITE) = WAIT_OBJECT_0 Then Begin
      L := fJobList.LockList;
      Try
        nextJob := L[0];
        If PassJobToNextPendingThread (nextJob) Then
          L.Delete(0)
        else
          ReleaseSemaphore (fSemaphore,1,nil); // Semaphore wieder erhöhen, das kein Thread gefunden wurde.
      finally  
        fJobList.UnlockList;
      End;
    End;
End;
Jeder Thread, der einen solchen Job ausführen soll, meldet sich bei der TJobList an.

Der Konstruktor der TJoblist könnte diese Threads auch selbst erzeugen (Maximale Anzahl als Parameter im Konstruktor). Alle Threads sind zunächst erstmal in Wartestellung ('Suspended').

Die Methode 'PassJobToNextPendingThread' sucht nun einfach den nächsten (oder ersten) freien Thread und übergibt den Job. Wenn ein Job vermittelt wurde, liefert die Funktion 'TRUE', sonst 'FALSE'. Der Thread beginnt seine Arbeit (ist also nicht mehr in Wartestellung). Der nächste eingehende Job wird dann einfach an den nächsten Thread vermittelt.

Delphi-Quellcode:
Constructor TJoblist.Create (aMaxThreads : Cardinal);
Var
  i : Integer;

Begin
  Inherited Create (True);
  fJoblist := TThreadList.Create;
  fThreadList := TList.Create; // Of TMyThread;

  For i:=1 to aMaxThreads do
    fThreadList.Add (TMyThread.Create (True)); // Alle Threads warten erstmal
  fSemaphore := CreateSemaphore (nil,0,maxint,nil);
  Resume;
End;

Destructor TJobList.Destroy;
Begin
  CloseHandle (fSemaphore);
  ClearThreadList;
  ClearJobList;
  fJobList.Free;
  fThreadList.Free;
End;

Function TJobList.PassJobToNextPendingThread (aJob : TJob);
Var
  i : Integer;

Begin
  For i:=0 To fThreadList.Count - 1 do
     If Not (TMyThread(fThreadList[i]).Suspended then Begin
       TMyThread(fThreadList[i]).Job := aJob;
       TMyThread(fThreadList[i]).Resume;
       Result := True;
       Exit;
     End;
  Result := False;
End;
So, es fehlt nur noch der TMyThread.

Ach ja, alles ungetestet und runtergerasselt. Wer Fehler findet, kann sie behalten.

7down 27. Jan 2007 09:41

Re: x Threads die gemeinsam eine Task-Liste abarbeiten, wie?
 
Wow danke euch beiden!

Habe mir deinen Source mal bisschen angesehn, leider versteh ich da nicht alles.
Mir wäre es lieber eine Liste zu haben, von mir aus ein Array of TJob, wobei TJob dann ein Record sein könnte mit sFile: String und bUploading: Boolean.

Anfangs ist bUploading überall False. Jetzt werden 10 Threads erstellt, die alle standartmäßig warten, bis ein Job da ist den sie sich holen können. Wichtig wäre noch, dass die Jobliste alle x Minuten aktualisiert werden würde, d.h. es kommen neue Jobs dazu.

So sollte das funktionieren.
Aber wie löse ich sowas?

Codeschnipsel wären nice, Codeschnipsel mit Erklärung wär :cheers:

;)

Danke schon mal,

Ciao
7down

alzaimar 27. Jan 2007 19:22

Re: x Threads die gemeinsam eine Task-Liste abarbeiten, wie?
 
Zitat:

Zitat von 7down
Codeschnipsel wären nice, Codeschnipsel mit Erklärung wär :cheers:

Cursor auf das, was Du nicht verstehtst, und 'F1' drücken. Sollte klappen.

7down 28. Jan 2007 10:33

Re: x Threads die gemeinsam eine Task-Liste abarbeiten, wie?
 
Hat keiner ne Idee wie ich das realisieren könnte, wie ich in meinem letzen Post geschrieben hab?

Gruß
7down

Pfoto 28. Jan 2007 10:40

Re: x Threads die gemeinsam eine Task-Liste abarbeiten, wie?
 
Hallo!

User alzaimar (der auch schon geantwortet hat), hatte
mal ein kleines Projekt-Beispiel hier gepostet.
Es dürfte genau das sein, was du suchst (mehrere Threads
arbeiten eine Liste ab etc...)


Schau mal in diesem Beitrag nach (gaaanz unten, ThreadsAndJobs.zip),
es hat mir persönlich sehr viel geholfen...
(auf diesem Weg einen großen Dank an Mitglied alzaimar!)


Gruß
Pfoto

Robert Marquardt 28. Jan 2007 11:25

Re: x Threads die gemeinsam eine Task-Liste abarbeiten, wie?
 
Wenn ich mich recht entsinne enthaelt Delphi eine threadsichere Variante der TstringList.

alzaimar 28. Jan 2007 11:38

Re: x Threads die gemeinsam eine Task-Liste abarbeiten, wie?
 
Dein Ansatz wird so nicht funktionieren, denn wenn zwei Thread einen Eintrag in der Jobliste gleichzeitig abarbeiten, hast Du schon ein Problem. Also musst du erstmal die Jobliste 'Threadsicher' machen, also sicherstellen, das nur jeweils ein Thread exklusiven Zugriff auf die Liste hat.

Du solltest Dich mit Synchronisationsmechanismen zwischen Threads beschäftigen, denn ein Codeschnipsel, das Du nicht verstehst, bringt Dir doch gar nichts.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:06 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-2025 by Thomas Breitkreuz