Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Mal wieder Threads.... (https://www.delphipraxis.net/146920-mal-wieder-threads.html)

DelTurbo 29. Jan 2010 12:24


Mal wieder Threads....
 
Hi,

ich suche seit heute morgen ein vernünftiges beispiel wie man "sauber" threads erstellt. Und zwar läuft es bei folgendermasen ab....

Ich habe eine sub. Die kennt ein Array z.b. so..
Delphi-Quellcode:
type
  TMyThread = record
   InUse     :Boolean;
   FormHandle :THandle;
   Text      :String;
   ..... usw.
end;
var
   MyThread :Array[0..20] of TMyThread;
Beim start des programms setze ich alle InUse auf false. Wenn ich einen Thread starten möchte, durchsuche ich MyThread ob ein InUse=False ist. Wenn ja dann setze ich es sofort auf True und übergebe den Index an meinen Thread.

Der Thread hohlt sich dann die nummer und hat damit ja zugriff auf den Text der ihm gehört. Beim beenden des Threads, also als letzte zeile setzte ich MyThread[Index].InUse:=False; damit er wieder frei ist.

Das hier ist ja nur ein beispiel. Es wird natürlich wesentlich mehr in dem Thread gemacht. Aber das ist ja erstmal egal für ein kleines beispiel.

Delphi-Quellcode:
function GeloesterThread(varptr: Pointer): LongInt; stdcall;
var
  i :Integer;
begin
  i:=integer(varptr^);
  //in i steht dann der index
  MyThread[i].InUse:=False;
end;
So starte ich den

Delphi-Quellcode:
ThreadHandle:=CreateThread(nil, 0, TFNThreadStartRoutine(@GeloesterThread),@index, 0, id);
if ThreadHandle<>0 then CloseHandle(ThreadHandle);
Es klappt auch soweit. Aber es scheppert doch relativ oft. Und ich kann leider nicht nachvollziehen wie, wo und warum.

Nun habe ich gelesen man muss das mit TThread / BeginThread machen. Aber ich finde kein einfaches beispiel was auf meine sache zutrifft.

Wär super wenn mir einer helfen könnte. Ich komme einfach nichtmehr weiter. Es ist auch sehr sehr frustrierend wenn man stundenlang sucht und nix "richtiges" findet. Am geilsten wäre natürlich ein "richtiges" beispiel.

Vielen dank im voraus

Luckie 29. Jan 2010 12:31

Re: Mal wieder Threads....
 
Was machst du denn im Thread? Und die Forensuche nach Delphi-Referenz durchsuchenBeginThread hat keine brauchbaren Ergebnisse gebracht? Eventuell hilft auch die Suche nach Delphi-Referenz durchsuchenThread pool.

DelTurbo 29. Jan 2010 12:42

Re: Mal wieder Threads....
 
Nein, die beispiele die ich gefunden habe hängen immer an dieser Form1. Aber ich habe das als komplett eigene unit gemacht.

Beispiel von gestern abend. Es liefen 16 Threads. Der nächste der kam meinte er wäre thread 38?!?

Ich denke mal das mit dem Thread ablösen habe ich nicht verstanden. Ich weiss zwar was ich proggen möchte, aber wenn einem die syntax fehlt kommt man nicht weiter.

Deswegen auch die bitte nach einem Beispiel.

Gruss

Astat 29. Jan 2010 12:43

Re: Mal wieder Threads....
 
Hallo DelTurbo, such nicht nach einem Thread der nichts tut, sondern lass dass den Threads selber machen.
Schreib alles was abzuarbeiten ist in einen Buffer (Ringbuffer), triggere ein Event und die Threads wachen auf, und bearbeiten
die Daten usw. und so fort.

implementation 29. Jan 2010 13:00

Re: Mal wieder Threads....
 
Zitat:

Zitat von DelTurbo
Delphi-Quellcode:
ThreadHandle:=CreateThread(nil, 0, TFNThreadStartRoutine(@GeloesterThread),@index, 0, id);
if ThreadHandle<>0 then CloseHandle(ThreadHandle);
Nun habe ich gelesen man muss das mit TThread / BeginThread machen. Aber ich finde kein einfaches beispiel was auf meine sache zutrifft.

Es gibt drei Möglichkeiten, einen Thread zu starten.
Du benutzt direkt die WinAPI-Funktionen.
Und da brauchst du auch kein System.BeginThread. Das gehört nämlich zur zweiten Möglichkeit.
Die Nutzung von TThread ist die dritte Möglichkeit und kommt aus der RTL.

Diese drei Wege solltest du trennen, wenn du CreateThread benutzt, brauchst du weder BeginThread noch TThread.

sirius 29. Jan 2010 13:18

Re: Mal wieder Threads....
 
Nie CreateThread benutzen (zumindest bis D2006)! Nimm BeginThread!
BeginThread macht auch nix weiter als CreateThread aufzurufen und den Speichermanager darüber zu informieren, dass er jetzt bei der Speicherreservierung mit CriticalSections arbeiten muss. Und der zweite Teil ist extrem wichtig.
(Zudem muss deine ThreadProc jetzt nicht stdcall sein, sondern der Standard register reicht)

DelTurbo 29. Jan 2010 13:30

Re: Mal wieder Threads....
 
Ui, ich hatte mal BeginThread genommen. Aber das ging nicht. Ich hatte das stdcall nicht weggemacht. Nun wo es weg ist läuft es.

Wie stabil es läuft kann ich leider nicht sofort sagen. Da muss ich abwarten.

Vielen vielen dank, ich hoffe das rennt nun stabiler.

DelTurbo 29. Jan 2010 13:52

Re: Mal wieder Threads....
 
Muss ich da auf nochwas achten? Oder wirklich nur Create gegen Begin tauschen und das stdcall rausnehmen?

sirius 29. Jan 2010 14:12

Re: Mal wieder Threads....
 
Zu dem Unterschied CreateThread und Beginthread ist das alles.

Zu deiner Vorgehensweise hat ja Astat schon was gesagt (bzw. wie man es besser machen sollte). Wenn du es so beibehälst, kann ich dir zumindest sagen, dass an der Übergabe des Index etwas falsch ist. Du übergibst einen Pointer auf eine (möglicherweise sogar lokale) Variable, welche womöglich beim Start des threads gar nicht mehr existiert. Übergib doch den index direkt (kannst ja in der ThreadProc einfach pointer durch integer ersetzen), oder übergib gleich einen Pointer auf deinen Record (der ja anscheinend die Lebenszeit eines Threads überdauert)

DelTurbo 29. Jan 2010 14:34

Re: Mal wieder Threads....
 
Ich hätte auch viel viel lieber den Index-Wert übergeben. Aber in dem beispiel was ich gefunden hatte war es halt so.

Wie gesagt, mit der Syntax hackt es bei noch.

DelTurbo 29. Jan 2010 15:08

Re: Mal wieder Threads....
 
@sirius: Der Pointer den ich da übergebe zeigt ins array auf die nummer die für den thread zuständig ist. Da dürfte wohl nix passieren.

sirius 29. Jan 2010 15:14

Re: Mal wieder Threads....
 
Da steht aber nur index. Und wo ist die Variable index deklariert?

DelTurbo 29. Jan 2010 15:21

Re: Mal wieder Threads....
 
Das ist doch nur ein beispiel. Das ist nichtmal meine orginal Source. Das habe ich eben hier im post getippert um zu veranschaulichen was ich meine.

Hier der orginal aufruf.

FThread[i].ThreadHandle:=BeginThread(nil, 0, @FMake,@FThread[i].MyID, 0, FThread[i].ThreadID);

sirius 29. Jan 2010 15:26

Re: Mal wieder Threads....
 
Ah, ok. Aber du kannst doch gleich den Pointer auf den Record übergeben:
Delphi-Quellcode:
type
  PMyThread = ^TmyThread;
  TMyThread = record
   InUse     :Boolean;
   FormHandle :THandle;
   Text      :String;
   ..... usw.
end;
var
   FThread :Array[0..20] of TMyThread;



function GeloesterThread(MyThread: PmyThread): LongInt; stdcall;
begin
    //in i steht dann der index
  MyThread.InUse:=False;
end;



FThread[i].ThreadHandle:=BeginThread(nil, 0, @FMake,integer(@FThread[i]), 0, FThread[i].ThreadID);

DelTurbo 29. Jan 2010 15:41

Re: Mal wieder Threads....
 
Naja, das ist doch wie gehopst und gesprungen. Ich sagte ich habe probs mit der Syntax, nicht das ich nicht weiss was ich mache :zwinker:

Wobei.... so genau weiss ich eh nie was ich mache :-D

DelTurbo 30. Jan 2010 11:51

Re: Mal wieder Threads....
 
Rückmeldung!!

Das mit BeginThread hat mein prob gelöst. Nun rennt es sauber. Im moment laufen 14 Threads sauber "nebeneinander". Gibt es da eine obergrenze? Ich habe im moment bis zu 100 threads vorgesehen.

Nochmal danke für den tipp. :thumb:

Luckie 30. Jan 2010 12:10

Re: Mal wieder Threads....
 
So viel, bis der Speicher ausgeht. Aber was machen deine Threads? Je nach Aufgabe können Threads auch kontra produktiv sein.

sirius 30. Jan 2010 12:32

Re: Mal wieder Threads....
 
Zitat:

Zitat von Luckie
So viel, bis der Speicher ausgeht.

Das ist die Grenze für schlafende Threads. Gleichzeitig laufen sollten aber maximal 16.

Luckie 30. Jan 2010 13:49

Re: Mal wieder Threads....
 
Wo kann ich das nachlesen? 16 kommt mir dich etwas wenig vor.

mkinzler 30. Jan 2010 13:52

Re: Mal wieder Threads....
 
Zitat:

Zitat von Luckie
Wo kann ich das nachlesen? 16 kommt mir dich etwas wenig vor.

Wenn man die vom System (andere Benutzer) mitzählt auf jeden fall.

Luckie 3. Feb 2010 16:53

Re: Mal wieder Threads....
 
Zitat:

Zitat von sirius
Zitat:

Zitat von Luckie
So viel, bis der Speicher ausgeht.

Das ist die Grenze für schlafende Threads. Gleichzeitig laufen sollten aber maximal 16.

Ich habe mich noch mal umgesehen, da mir das mit den 16 Threads keine Ruhe gelassen hat. Diese Portscanner:
http://www.delphipraxis.net/internal...canner&start=0 und
http://www.delphipraxis.net/internal...?p=47533#47533
laufen mit deutlich mehr als 16 aktiven Threads.

DelTurbo 3. Feb 2010 16:58

Re: Mal wieder Threads....
 
Ich hatte gestern 31 laufen. Ohne probs. Im moment laufen *nachguck* 11. Also Peak war bisher 31.

Luckie 3. Feb 2010 17:09

Re: Mal wieder Threads....
 
Ich hatte schon über 1000 laufen, allerdings wie viele davon tatsächlich aktiv waren kann ich nicht genau sagen. Aber bestimmt mehr als 16. Aber ich denke, in so einem Fall ist es ganz sinnvoll, wenn man Priorität der Threads runtersetzt.

mjustin 3. Feb 2010 18:15

Re: Mal wieder Threads....
 
Zitat:

Zitat von Luckie
Ich hatte schon über 1000 laufen, allerdings wie viele davon tatsächlich aktiv waren kann ich nicht genau sagen. Aber bestimmt mehr als 16. Aber ich denke, in so einem Fall ist es ganz sinnvoll, wenn man Priorität der Threads runtersetzt.

55.000 threads sind schon machbar (mit 2GB RAM):

http://blogs.technet.com/markrussino...8/3261309.aspx

Cheers,
Michael

Astat 3. Feb 2010 22:16

Re: Mal wieder Threads....
 
Zitat:

Zitat von DelTurbo
Gibt es da eine obergrenze? Ich habe im moment bis zu 100 threads vorgesehen.

Hallo DelTurbo, ja.

1. Die Stack Size und der zur Verfügung stehende Speicher (RAM)
2. Die Kosten für Threadswitching

Microsoft empfiehlt für Serveranwendung die hohe Last für einzelne Requests erzeugen, auf modernen Xeon Systemen maximal 8 Threads per CPU.

Dh. Das Limit liegt genau dort, wo das Verhältnis der Verwaltungszeit (CPU-Takte für den aufwendigen Threadwechsel)
zum tatsächlichen Nutzen für die Anwendung zu kostspielig wird.

Anderst ausgedrückt, je mehr ein Thread arbeiten muss, desto weniger können kostengünstig verwendet werden.

Perfmon liefert dafür ausagekräftige Werte (Processor Queue Length)

lg. Astat


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