Delphi-PRAXiS
Seite 1 von 2  1 2   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   Workerthread: Der Diener im Hintergrund (https://www.delphipraxis.net/93835-workerthread-der-diener-im-hintergrund.html)

alzaimar 12. Jun 2007 08:19


Workerthread: Der Diener im Hintergrund
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

Threads sind eine tolle Sache. Wenn man sie versteht. Wenn nicht, bringen sie einen an den Rand des Wahnsinns. Oder ein Stück weiter. Ich weiss, wovon ich rede. :roteyes:

Ich benötige für meine Applikationen immer mal wieder einen Thread, der ab und zu einzelne Jobs im Hintergrund ausführen muss. Wenn man z.B. auf bestimmte Ereignisse reagieren muss, diese Reaktion aber zeitaufwändig ist, dann kann die Ereignisbehandlung während der Ausführung des Eventhandlers blockiert sein.

Also habe ich einen generischen Thread implementiert, der einzelne Aufgaben (Jobs) im Hintergrund abarbeitet. Ich muss dazu nur den Job selbst definieren, alles Andere macht dieser Thread. Diese Threads nennen sich auch 'worker threads', weil sie eben ankommende Arbeiten ausführen.

So ein Job kann z.B. das Einlesen einer Tabelle von einer Datenbank sein, oder auch das Abspeichern von Daten.

Die Unit instantiiert einen Workerthread 'PendingJobs', den man sofort mit Arbeit befüllen kann. Dazu ruft man einfach die 'AddJob'-Methode auf:
Delphi-Quellcode:
...
PendingJob.AddJob (TMyJob.Create);
...
Die Anweisung schiebt den Job ans Ende der Jobliste und aktiviert ggf. den Thread (wenn der nicht sowieso schon aktiv ist). Der TMyJob wird dann 'demnächst' im Hintergrund ausgeführt.

Wenn man einen Job definiert, der mit COM-Objekten arbeitet (z.B. ADO) dann setzt man die Eigenschaft 'UsesCOMObjects' des Jobs auf True.


Der Thread verwendet eine Semaphore sowie eine Threadliste (die Liste der noch nicht ausgeführten Jobs). Auf Schnickschnack habe ich verzichtet, das kann jeder selbst einbauen.

Ich habe die Unit sowie eine kleine bescheuerte Demo bereitgestellt, die jedoch zeigt, wie einfach man Hintergrundarbeiten in seiner Anwendung implementieren kann.

Kritik, Verbesserungs- und Erweiterungsvorschläge sind ausdrücklich erwünscht.

Viel Spaß damit.

Update: Die Idee von thkerkmann wurde aufgenommen: Die Synchronize-Methode des Workerthreads ist nun public und kann innerhalb der TJob.Execute-Methode aufgrufen werden.

Update: Idee von shmia: Exception-Notification Event, und eine verbesserte Beendigung des Workerthreads. Man kann unn steuern, ob vor Beendigung alle ausstehenden Jobs noch abgearbeitet werden sollen oder nicht.

Update: Aus dem Thread wurde ein Threadpool (Idee von shmia). Er ist in einer wackeligen Version fertig. Er läuft in der Demo stabil, aber was heißt das schon. Ich würde Euch bitten, mal kräftig gegen die Klasse zu treten. Mal sehen, was sie aushält.

Der Threadpool verwaltet mehrere Threads (Anzahl einstellbar, auch zur Laufzeit), die gemeinsam die oben erwähnte Jobliste abarbeiten.

Update vom Threadpool: Schleifenvariablen als Cardinal deklariert, wenn Schleifenende = 'X-1', und X=0, bombt es.

Update vom Threadpool: Memoryleak beim Beenden beseitigt. Weiterhin stellt die Unit keine Instanz 'PendingJobs' mehr bereit. Denn das wurde im Finalisierungsabschnitt der Unit wieder freigegeben. Wenn die Classes-Unit ihren Finalisierungsabschnitt schon durchlaufen hat, gibt es Probleme.

Update vom Threadpool: Das Herabsetzen der Poolsize zur Laufzeit führte zu einem Speicherleck, ein fehlendes 'UnlockList' im der Clear-Methode der JobList und noch ein paar Kommentare.

Update vom Threadpool: x000x hat einen Bug gefunden: Die Setter-Methode des OnJobException-Events muss den Methodenzeiger natürlich an die einzelnen Threads weiterleiten. Weiterhin habe ich die Workerthread-Unit rausgenommen. Man braucht sie nicht mehr.

Update vom Threadpool: Die aktuelle Version läuft stabil, sie ist in einer Kundenanwendung im Einsatz.

Update vom Threadpool: Neue Methode, um aus einem Job heraus Nachrichten zu verschicken (siehe beiliegende Demo).

Update: Eigenschaft 'Terminated' des TWorkerThread wird publiziert, kleiner Fehler in der Clear-Methode beseitigt.

Update: Kleiner Hack, um den Threadnamen zu setzen (Debugginghilfe). Dank an Assertor.

thkerkmann 12. Jun 2007 08:54

Re: Workerthread: Der Diener im Hintergrund
 
Hi Alzaimar,

geniale Klasse.

Eins hab ich aber nicht ganz verstanden:

Wenn man Synchronized auf true setzt, wird der ganze Job über Synchronize(Run) ausgeführt. Wird das nicht zu einer blockierenden Operation dann ? Dann kann ich doch eigentlich diese Arbeit gleich im Haupt-VCL-thread ausführen lassen.

oder fehlt mir da was ?

Gruss

alzaimar 12. Jun 2007 09:20

Re: Workerthread: Der Diener im Hintergrund
 
:gruebel: stimmt auffallend...

Ich habe z.B. eine 'TDisplayJob' Klasse, die bestimmte Ergebnisse, die ein anderer Job ermittelt hat, irgendwo reinzeichnet. Der eine Berechnungsjob befüllt also die Jobliste mit einem Synchronized-Job zur Darstellung.

Um das in einem Job zu erledigen, müsste ich ein paar Sachen umstricken (Synchronized-Methode des worker threads als public deklarieren und Parameterliste der TJob.Execute-Methode ändern).

Ich mach mir darüber aber mal Gedanken, obwohl die Arbeitsteilung (Berechnung: Synchronized = False, Darstellung: Synchronized = True) ganz elegant ist.

Danke für den Hinweis.

mschaefer 12. Jun 2007 22:40

Re: Workerthread: Der Diener im Hintergrund
 
Eigentlich hört sich das ganz interesssant an. Werd mir das morgen mal genauer anschauen..

Grüße // Martin

Luckie 13. Jun 2007 00:14

Re: Workerthread: Der Diener im Hintergrund
 
Warum so kompliziert. Man kann auch Windows das ganze machen lassen: MSDN-Library durchsuchenQueueUserWorkItem.
Delphi-Quellcode:
function Thread(p: Pointer): Integer; stdcall;
var
  LBIndex               : Cardinal;
  Cnt                   : Cardinal;
begin
  LBIndex := PThreadParams(p)^.LBIndex;
  TListbox(frmReceiver.FindComponent('Listbox' + IntToStr(LBIndex))).Items.Clear;
  for cnt := 0 to 29 do
  begin
    TListbox(frmReceiver.FindComponent('Listbox' + IntToStr(LBIndex))).Items.Add(IntToStr(cnt));
    sleep(100);
  end;
  result := 0;
end;

procedure TfrmReceiver.WMCOPYDATA(var msg: TWMCopyData);
var
  idx                   : Integer;
  ThreadParams          : PThreadParams;
begin
  idx := PMyRecord(msg.CopyDataStruct.lpData)^.idx;
  New(ThreadParams);
  ThreadParams.LBIndex := idx;
  if QueueUserWorkItem(@Thread, ThreadParams, WT_EXECUTEDEFAULT or 2 shl 16) = 0 then
    ShowMessage(SysErrorMessage(GetLastError));
end;

WS1976 13. Jun 2007 06:12

Re: Workerthread: Der Diener im Hintergrund
 
Hallo alzaimar,

ich finde deinen Code Klasse! Ob das Ganze nötig ist oder nicht muss man sicherlich im Einzelfall überprüfen. Schon alleine um dahinterzukommen wie Threads funktionieren hat sich die Arbeit gelohnt.
sehr guter Code.
sehr gut kommentiert.
( aber schnapp jetzt bitte nicht über )

Gruss
Rainer

alzaimar 13. Jun 2007 07:48

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von WS1976
ich finde deinen Code Klasse!

Danke
Zitat:

Zitat von WS1976
Ob das Ganze nötig ist oder nicht muss man sicherlich im Einzelfall überprüfen.

Wir haben hier ein Messaging-System, wobei die Clients per UDP Änderungen an einem Datenbestand mitgeteilt bekommen. Das Problem ist, das die Daten sowohl in eine interne Struktur eingepflegt, als auch visualisiert werden müssen. Teilweise rattern 100te von Paketen pro Sekunde ein. Damit die Anwendung nicht einfriert, schiebt der Empfangs-Event des UDP-Clients die vorzunehmenden Änderungen in die Jobliste. Die Visualisierung geschieht im OnIdle der Anwendung. Weiterhin müssen die Pakete jedoch an andere Programmteile weitergeleitet werden: auch dafür haben wir einen Job definiert. So ist gewährleistet, das es zu keiner Zeit zu irgendwelchen Verzögerungen kommt, auch wenn es kurzzeitig zu UDP-Bursts kommt.

Wir hatten vorher den Workerthread im Rahmen einer garbage collection im Einsatz, wo Zigtausende von Objekten freigegeben werden mussten. Das dauert doch ein paar Sekunden. Also haben wir Jobs definiert, die jeweils einige hundert Objekte freigeben. Damit läuft die Anwendung wieder flüssig.
Zitat:

Zitat von WS1976
Schon alleine um dahinterzukommen wie Threads funktionieren hat sich die Arbeit gelohnt.

Du hast mich durchschaut. Das war die Motivation für mich, diesen Code hier zu posten, weil viele hier Probleme mit Threads haben. Insbesondere die Verwendung der Semaphore als wirkungsvollere Alternative zum 'Resume/Suspend'-Mechanismus sowie das externe Antriggern des Threads ist es Wert, mal analysiert zu werden.

Weiterhin habe ich nur unglaublich komplexe Units zum Thema 'Worker threads' gefunden. Da dachte ich mir eben: Nö. Muss einfacher gehen.
Zitat:

Zitat von WS1976
( aber schnapp jetzt bitte nicht über )

Geht nicht. Zu alt. :zwinker:

@Luckie: Oder so. :) Da lernt man aber nix über Threads.

shmia 13. Jun 2007 19:17

Re: Workerthread: Der Diener im Hintergrund
 
Ist es nicht so, dass Exceptions innnerhalb von Threads ins Nirvana gehen?
Man könnte diese aber über ein Event an die Applikation weiterreichen.
Delphi-Quellcode:
Procedure TWorkerThread.Run;
// Kleine Hilfsprozedur, die den aktuellen Job ausführt.
Begin
  Try
    If fCurrentJob.UsesCOMObjects and not fCOMInitialized Then Begin
      fCOMInitialized := True;
      CoInitialize(Nil)
    End;
    fCurrentJob.execute(Self);
  Except
     // die Exception wurde nicht innerhalb des Jobs behandelt
     if Assigned(FOnException) then
        // Event auslösen
        FOnException(fCurrentJob, ExceptObject);
  End;
  fCurrentJob.Free;
End;
Man könnte den TNopJob vermeiden, wenn man so ändert:

Delphi-Quellcode:
Procedure TWorkerThread.Execute;
// Arbeitsschleife des Workerthreads. Er wartet, bis die Semaphore aktiv ist.
// Dann wird der nächste Job aus der Jobliste extrahiert und abgearbeitet.
Var
  L: TList;
Begin
  While Not Terminated Do
    If WaitForSingleObject(fSemaphore, INFINITE) = WAIT_OBJECT_0 Then
  Begin
     if Terminated then Exit; // <===== Ausstieg, falls Kill aufgerufen wurde
      L := fJobs.LockList;
      Try
   If l.count > 0 Then
         Begin
     fCurrentJob := TWorkerThreadJob(L[0]);
     l.Delete(0);
   End;
      Finally
   fJobs.UnlockList;
      End;
       If fCurrentJob.Synchronized Then
   Synchronize(Run)
       Else
   Run;
    End;
End;

Procedure TWorkerThread.Kill;
Begin
  ReleaseSemaphore(fSemaphore, 1, Nil)  // <=====
  Terminate;
End;

alzaimar 14. Jun 2007 08:56

Re: Workerthread: Der Diener im Hintergrund
 
Hi shmia,

Das mit dem Beenden ist so eine Sache: Deine Idee ist gut, hat aber eine Schwachstelle:
Du rufst Kill auf.
Kill ruft ReleaseSemaphore auf. Dann wird in der Execute-Methode WaitForSingleObjects verlassen und kein Job ausgeführt. Wenn nun wieder WaitForSingleObjects aufgerufen wird, *bevor* in der Kill-Methode die 2.Zeile ausgeführt wurde, hängt die Chose immer noch.

Wenn überhaupt, dann anders herum: Also erst Terminate und dann ReleaseSemaphore.
Ich habe mich jedoch dagegen entschieden:
1. TNopJob ist ein nettes Beispiel, wie man einen Job deklariert.
2. Ich mag es nicht, zentrale Funktionsaufrufe (wie hier: ReleaseSemaphore) an zwei Stellen im Code aufzurufen.
3. Die Abfrage 'If Terminated' ist immer (bis auf 1x) überflüssig.


Besser wäre es (finde ich), das Resultat von 'WaitForSingleObject' auszuwerten:

Delphi-Quellcode:
Procedure TWorkerThread.Execute;
...
Begin
  While Not Terminated Do
    Case WaitForSingleObject(fSemaphore, INFINITE) Of
      WAIT_ABANDONED : // Passiert, wenn das Handle geschlossen wurde
        Break;
      WAIT_OBJECT_0 : Begin
      ... // Hier Job extrahieren und ausführen
      End
  End;
End;

Procedure TWorkerThread.Kill;
Begin
  Terminate;
  CloseHandle (fSemaphore);
End;
Und den Destruktor anpassen. Ich habe es noch etwas komfortabler gemacht (siehe oben).

Das wäre eventuell akzeptabel.

Die Sache mit den Exceptions habe ich bewusst dem Job überlassen. Der soll mit Exceptions umgehen und weiss am Besten, was zu tun ist. Wenn ihn das nicht interessiert, dann muss er keinerlei Vorkehrungen treffen, den der Workerthread macht das.

Es schadet nicht, und wer's braucht... Also... wird eingepflegt.

*einpfleg* hmmm.. Wenn der Job nicht synchronisiert ist, aber in der Exception-Routine die VCL zur Darstellung verwendet wird, dann hängt die Anwendung bzw. schmiert irgendwann ab. Also muss man den Aufruf des Events synchronisieren. *hack* Fettich.

kalmi01 14. Jun 2007 10:59

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von alzaimar
Also muss man den Aufruf des Events synchronisieren. *hack* Fettich.

Und wo iss "Fettich" ?

alzaimar 14. Jun 2007 11:03

Re: Workerthread: Der Diener im Hintergrund
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich kann meinen Beitrag oben nicht mehr editieren, weil er zu alt ist. Ich hab Matze gefragt, was ich tun soll.

Aber hier ist die Version, die irgendwann im 1.Post sein wird.

shmia 14. Jun 2007 11:58

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Kritik, Verbesserungs- und Erweiterungsvorschläge sind ausdrücklich erwünscht.
Also ich bin soweit ganz zufrieden. :thumb:
Aber das Non Plus Ultra wäre ein Thread-Pool, der die Jobs abarbeitet.
Man gibt die max. Anzahl von WorkerThreads vor, die alle auf die gleiche Jobliste zugreifen.
Angenommen man möchte 500 Webseiten downloaden und sieht max 10 parallel arbeitende Threads vor.
Jeder der 10 Threads krallt sich einen Job, arbeitet diesen ab, und wenn er fertig ist schaut er in der Jobliste, ob noch was zu tun ist.

Die Krönung wäre dann folgendes Verhalten:
Wenn ein Thread länger als 10 Sekunden nichts zu tun hat (weil Jobliste leer ist), beendet er sich automatisch.

alzaimar 14. Jun 2007 12:09

Re: Workerthread: Der Diener im Hintergrund
 
Oho. Lustig. Soll ich? :mrgreen:

Bis auf 'die Krönung'. Die ist eigentlich unnötig, weil WaitForSingleObject keine CPU-Zeit verbrät. Mal sehen.

Ich glaub, ich bastel das heut abend.

kalmi01 14. Jun 2007 12:14

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Ich glaub, ich bastel das heut abend.
Aber hier einstellen nich vergessen :wink:

alzaimar 14. Jun 2007 12:18

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von kalmi01
Zitat:

Ich glaub, ich bastel das heut abend.
Aber hier einstellen nich vergessen :wink:

Nö. Nachher haben andere noch was davon. Nö Nö. Ich poste ein HEX-Listing zum abtippen. :stupid:

kalmi01 14. Jun 2007 13:01

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von alzaimar
Nö Nö. Ich poste ein HEX-Listing zum abtippen. :stupid:

vom Source, oder von der ZIP-Datei, mit den dcu's für alle Delphi-Releases :twisted:

alzaimar 14. Jun 2007 13:20

Re: Workerthread: Der Diener im Hintergrund
 
Von der ZIP-Datei? Das ist gemein. Nee, nee, sind wir mal nicht so: Hex-Listing vom verschlüsselten Sourcecode! :lol:

Elvis 14. Jun 2007 13:39

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von alzaimar
Von der ZIP-Datei? Das ist gemein. Nee, nee, sind wir mal nicht so: Hex-Listing vom verschlüsselten Sourcecode! :lol:

Mönsch! Gleich 3 Dinge auf einma:l Spannung, Spiel und Schoko.... source code. :freak:

sh17 14. Jun 2007 13:48

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von Elvis
Zitat:

Zitat von alzaimar
Von der ZIP-Datei? Das ist gemein. Nee, nee, sind wir mal nicht so: Hex-Listing vom verschlüsselten Sourcecode! :lol:

Mönsch! Gleich 3 Dinge auf einma:l Spannung, Spiel und Schoko.... source code. :freak:

Und der Key ist der Happy-Code in jedem 7. Thread.

Daniel 14. Jun 2007 14:05

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von alzaimar
Ich kann meinen Beitrag oben nicht mehr editieren, weil er zu alt ist.

:shock:
Kinderchen, so sagt doch was. :stupid: Ich habe die Edit-Limitierung aus dieser Rubrik jetzt rausgenommen. *zupf*

alzaimar 14. Jun 2007 14:12

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von Daniel
Zitat:

Zitat von alzaimar
Ich kann meinen Beitrag oben nicht mehr editieren, weil er zu alt ist.

:shock:
Kinderchen, so sagt doch was. :stupid: Ich habe die Edit-Limitierung aus dieser Rubrik jetzt rausgenommen. *zupf*

Papi, hab ich, aber ich hab Onkel Matze Bescheid gesagt, oder pennt der noch?

Jut, dann werdick mal, gelle?

[edit]lethargische Unterstellungen hinzugefügt[/edit]

alzaimar 14. Jun 2007 23:28

Re: Workerthread: Der Diener im Hintergrund
 
Threadpool Version 0.1 fertig zum Testen und im 1.Post verfügbar.

kalmi01 15. Jun 2007 13:30

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von alzaimar
Threadpool Version 0.1 fertig zum Testen und im 1.Post verfügbar.

Jau,
und da dab ich auch gleich auf einen Fehler, Prog einfach über Close-Button schliessen:
Delphi-Quellcode:
Destructor TWorkerThreadJobList.Destroy;
Begin
  Clear;
  fJobs.Free;                       <<< EListError: Listenindex überschreitet Maximum(0)
  CloseHandle(fSemaphore);
End;
Memory-Leak in Zeile 154 der csWorkerThreadPool.pas:
Delphi-Quellcode:
    For i := 0 To L.Count - 1 Do
      TWorkerThreadJob(L[i]).Free;     <<<< hier
    L.Clear;
Memory-Leak in der finalization

kalmi01 15. Jun 2007 13:32

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von alzaimar
Die beiden Units (csWorkerThread und csWorkerThreadpool) verwenden teilweise die gleichen Bezeichner, sollten also nicht gemeinsam in einem Projekt verwendet werden.

Hab mir den Code noch nicht näher angesehen, aber lässt sich das nicht sinnvoller Weis zusammenführen ?

alzaimar 15. Jun 2007 13:42

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von kalmi01
Zitat:

Zitat von alzaimar
Die beiden Units (csWorkerThread und csWorkerThreadpool) verwenden teilweise die gleichen Bezeichner, sollten also nicht gemeinsam in einem Projekt verwendet werden.

Hab mir den Code noch nicht näher angesehen, aber lässt sich das nicht sinnvoller Weis zusammenführen ?

Na ja, vielleicht. Ich wüsste aber nicht, wieso. Denn Du kannst auch einfach einen ThreadPool mit einem Thread instantiieren und dann hast Du das gleiche Ergebnis.

alzaimar 15. Jun 2007 13:49

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von kalmi01
Delphi-Quellcode:
    For i := 0 To L.Count - 1 Do
      TWorkerThreadJob(L[i]).Free;     <<<< hier
    L.Clear;
Memory-Leak in der finalization

Schleifenvariable ist Cardinal, L.Count (=0) - 1 als Cardinal gecastet ist dann doch etwas zu groß.. Daher der Müll..

Neue Version im 1.Post

kalmi01 15. Jun 2007 14:14

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von alzaimar
Neue Version im 1.Post

Demoprog starten und sofort wieder schliessen ==> Memory-Leak weil fThreadPool nicht wieder freigegeben wird.

alzaimar 15. Jun 2007 15:33

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von kalmi01
Zitat:

Zitat von alzaimar
Neue Version im 1.Post

Demoprog starten und sofort wieder schliessen ==> Memory-Leak weil fThreadPool nicht wieder freigegeben wird.

Fertig. Das war kniffeliger, als gedacht. Leider gibt es keine fertige Instanz 'PendingJobs' mehr, denn die Freigabe im Finalisierungsabschnitt kann nach der Classes-Finalisierung passieren, was bedingt durch die Verwendung von TThreads schmerzhaft und peinlich wird (wegen RTE 216).

Neue Version im 1.Post

Los, weitere Probleme :bounce1: ?

kalmi01 15. Jun 2007 15:44

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von alzaimar
Los, weitere Probleme :bounce1: ?

Demoprog starten und (versuchen) wieder zu schliessen ==> Geht nicht, Fenster bleibt stehen.

alzaimar 15. Jun 2007 16:33

Re: Workerthread: Der Diener im Hintergrund
 
Komisch, bei mir nicht... 100 Versuche, 100 mal korrekt geschlossen. Vermutlich hast du einen langsameren Rechner ...

Das Beenden von Threads beim Programmende ist nicht Ohne, aber wenn es hier funktioniert, kann ich leider keine 'Abhilfe' schaffen. Dummerweise sind auch Versuche, eine Multithreadinganwendung zu debuggen, sehr komplex, da sich die IDE sehr oft aufhängt.

klick mal auf 'Terminate', das ruft Destroy auf und erstellt den Pool anschließend wieder.

mschaefer 15. Jun 2007 16:58

Re: Workerthread: Der Diener im Hintergrund
 
Moin, moin

Delphi-Quellcode:
   TWorkerThreadJob(L[i]).Free;
Gefühlt würde ich Destroy vorziehen.
// Martin

alzaimar 15. Jun 2007 17:29

Re: Workerthread: Der Diener im Hintergrund
 
Und ich dachte, man soll immer 'Free' verwenden, denn Free prüft nur noch, ob die Instanz<>nil ist.

kalmi01 15. Jun 2007 17:57

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von mschaefer
Delphi-Quellcode:
   TWorkerThreadJob(L[i]).Free;
Gefühlt würde ich Destroy vorziehen.
// Martin

Nee, nee, Free ist schon richtig.
Destroy soll man nicht nehmen.

Zitat:

Das Beenden von Threads beim Programmende ist nicht Ohne
ich habe ja garnicht erst welche erzeugt.
Demo-Prog einfach nur starten und sofort wieder mit [x] schliessen ==> hängt.

kalmi01 15. Jun 2007 18:14

Re: Workerthread: Der Diener im Hintergrund
 
Sodele,

hab noch mal auf einer anderen (langsameren Maschine) getestet, es geht.
Ebenso Dein "Spezial-Test-Prog", alles so wie es soll.

alzaimar 15. Jun 2007 20:56

Re: Workerthread: Der Diener im Hintergrund
 
kalmi01, Du erzeugst die Threads, wenn Du den Threadpool instantiierst.

Läuft dann Alles so? Das wäre fein.

kalmi01 16. Jun 2007 12:19

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Läuft dann Alles so?
Daheim schon (Win2K-Pro), an der Arbeit (XP) konnt ich es jetzt noch nicht verifizieren.
Das gleiche Kompilat hat daheim keine Fehler gebracht, an der Arbeit aber Memory-Leaks.
OK, vielleicht liegt es "an der Arbeit" auch den schlechten Strahlen :thumb:

Ich teste Montag nochmal unter XP, vielleicht schaff ich es bis dahin, mir Deinen Source näher anzusehen.
Formatierst ja ein bischen anders als ich :cheers:

alzaimar 16. Jun 2007 13:52

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

Zitat von kalmi01
Formatierst ja ein bischen anders als ich :cheers:

DelForExp

kalmi01 16. Jun 2007 16:10

Re: Workerthread: Der Diener im Hintergrund
 
Zitat:

DelForExp
den hab ich noch nicht so hinbekommen, das der Code so formatirt ist, wie ich es möchte.
Beispiel:
Delphi-Quellcode:
if (...)
   or
   (...)
then begin
     end
else begin
     end;
oder:
Delphi-Quellcode:
for i := 0 to ...
do begin
   end;
und so weiter.

Ghostwalker 16. Jun 2007 20:50

Re: Workerthread: Der Diener im Hintergrund
 
Ich hab dein Demo hier mal unter XP (XP Pro SP2) laufen lassen. Tut ohne Probleme :)

kalmi01 18. Jun 2007 08:07

Re: Workerthread: Der Diener im Hintergrund
 
Moin, moin,
Zitat:

Zitat von alzaimar
kalmi01, Du erzeugst die Threads, wenn Du den Threadpool instantiierst.

Läuft dann Alles so? Das wäre fein.

Also mit der oberen Version von "csWorkerThreadPool.pas + Demo" werd ich auf meinem Arbeitsrechner (XP+SP2, P4 HT mit 2GB RAMBUS) nicht glücklich.
Das Ding hängt beim schliessen und ich möchte mal behaupten, das die Version (subjektiv) langsamer ist als der Vorgänger.
Wie schon gesagt, Daheim funktionierts.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:39 Uhr.
Seite 1 von 2  1 2   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz