Mehrere Threads mit gleicher ThreadProc



  • Ja natürlich. Völlig unbedenklich.



  • @WebFritzi

    Beim BCB gibt's doch 'nen TThread!

    Davon kannste eine eigene Klasse ableiten von der beliebig viele Instanzen erzeugt werden koennen.

    Ich mach das mit 'ner Datei- Suchfunktion. Die kann 'parallel' mehrere Suchen ausführen.

    !!! Du darfst aus dem Thread blos nicht auf alle VCL- Komponenten zugreifen - nur mit Synchronize();

    Oder hat Dein BCB 3 kein TThread, dann vergiss was ich sagte. 😉



  • Es ist also wirklich unbedenklich, wenn ich mehere Threads über ein und dieselbe ThreadProc laufen lasse, ja???

    Es ist genau dann unbedenklich, wenn alle Variablen, auf die von Threads zugegriffen wird, entweder im TLS (Thread local storage) liegen, eine Sychronisation des Zugriffs auf die Variable erfolgt, oder von der Variable einfach nur gelesen wird.



  • @Der Altenburger: Danke, aber TThread kenne ich schon lange. Wir sind hier im WinAPI-Forum. Schon vergessen? 😉

    @RenéG: Danke für deine Antwort. Ich weiß nicht, wie ich Variablen in den TLS bekomme. Meine Variablen befinden sich auf zweierlei Ebenen. Es gibt welche, die lokal in der ThreadProc angelegt werden (Stack). Liegen die dann im TLS? Andere Variablen hab ich auf dem Heap angelegt, allerdings nicht in der ThreadProc. Der ThreadProc wird ein Pointer mitgegeben, der auf eine Instanz meiner Thread-Klasse zeigt, die im Hauptthread angelegt wurde. In dieser Klasse befinden sich 3 Members vom Typ WCHAR* (auch auf dem Heap angelegt). Auf die greife ich in der ThreadProc zu. Ist mir das erlaubt?



  • @WebFritzi

    Ich hab da noch was gefunden. In meiner BCB-Hilfe steht:
    *

    Dann solltest Du nicht so betonen, dass Du mit BCB arbeitest! 🙂 Die Initialisierungs- Probleme kommen auch von BCB- Laufzeitbibliotheken. 😕

    PS: Halt mich raus!

    [ Dieser Beitrag wurde am 27.03.2003 um 18:21 Uhr von DerAltenburger editiert. ]



  • Original erstellt von DerAltenburger:
    Dann solltest Du nicht so betonen, dass Du mit BCB arbeitest! 🙂 Die Initialisierungs- Probleme kommen auch von BCB- Laufzeitbibliotheken.

    Du solltest mich langsam gut genug kennen und wissen, dass ich mich im BCB recht gut auskenne, dass ich also TThread kennen muss. Aber du hast recht... man weiß ja nie. 😉 Die Initialisierungs"probleme" haben übrigens nichts mit dem BCB zu tun.



  • Original erstellt von WebFritzi:
    Es gibt welche, die lokal in der ThreadProc angelegt werden (Stack). Liegen die dann im TLS?

    Jeder Thread hat seinen eigenen Stack.

    Andere Variablen hab ich auf dem Heap angelegt, allerdings nicht in der ThreadProc. Der ThreadProc wird ein Pointer mitgegeben, der auf eine Instanz meiner Thread-Klasse zeigt, die im Hauptthread angelegt wurde. In dieser Klasse befinden sich 3 Members vom Typ WCHAR* (auch auf dem Heap angelegt). Auf die greife ich in der ThreadProc zu. Ist mir das erlaubt?

    Klar, wenn du die Zugriffe synchronisierst. 🙂
    Wenn ein Thread gerade schreibend auf so eine Instanz zugreift, sollten die anderen überhaupt nicht darauf zugreifen können.



  • Original erstellt von cd9000:
    Jeder Thread hat seinen eigenen Stack.

    Ach ne... Ich fragte, ob die auf dem TLS liegen...

    Original erstellt von cd9000:
    Klar, wenn du die Zugriffe synchronisierst. 🙂
    Wenn ein Thread gerade schreibend auf so eine Instanz zugreift, sollten die anderen überhaupt nicht darauf zugreifen können.

    Ah, das ist das mit den Critical Sections, oder? Ich lese aber nur von den Variablen. Daher werde ich sowas wohl nicht benötigen.



  • Ob TLS oder (lokaler) Stack, ist doch wurscht, oder? 🙂



  • Original erstellt von cd9000:
    Ob TLS oder (lokaler) Stack, ist doch wurscht, oder? 🙂

    Ich weiß nicht, denn ich habe keine Ahnung, was der TLS ist...



  • guck doch in die hilfe. das heißt Thread Local Storage



  • Original erstellt von <g>:
    guck doch in die hilfe. das heißt Thread Local Storage

    Wenn du den Thread von vorne gelesen hättest, dann wüsstest du, dass ich das bereits weiß, du Idiot! Ich weiß aber nicht, WAS das ist.



  • Idiot

    DAS WILL ICH ÜBERHÖRT HABEN, DU ****** !! :o



  • P-E-N-N-E-R!!!



  • Hihi, wie schön, dass du dich ärgerst. Das war auch mein Ziel. 😃 :p



  • UND MEIN ZIEL WAR ES DICH ZU ERFREUEN!!! 🙂 🙂 🙂



  • Bakc on topic 🙄

    Der TLS ist eine vom Betriebssystem extra bereitgestellter Threadspezifischer Speicherbereich. Wenn man den nicht explizit anfragt, speichert man da auch nichts. Variablen auf dem Stack landen da jedenfalls nicht. Trotzdem sind die Stacks wie gesagt unabhängig voneinander.

    Globale Variablen oder welche aufm Heap die außerhalb der ThreadProc erstellt wurden, müssen per Mutex oder Critical Section vor Mehrfachzugriff geschützt werden. Am besten schaust du dir dazu CreateMutex, WaitForSingleObject bzw. CreateCriticalSection, EnterCriticalSection, LeaveCriticalSection an. Für deinen Bedarf, kommt mir zweiteres passender vor.

    Die Sache mit _beginthread ist übrigens nicht Borland-spezifisch, zumindest der VC hat sowas auch. Ich schätze alles in allem trifft das auf jede Runtime-Library zu, da jede Library irgendwann threadspezifisch was hat und das muss nunmal initialisiert werden.



  • Vielen Dank, TriPhoenix´! Endlich mal einer, der etwas informatives von sich gibt. 🙂 Nocheinmal eine Information zu meinen Variablen (wie ich es bisher gemacht habe):
    Ich habe eine Threadklasse erstellt, in der die Informationen für jeden Thread gespeichert sind, und für jeden Thread wird eine Instanz davon auf dem Heap erstellt und die Members gefüllt (ebenfalls auf dem Heap). Das heißt: Die Infos der einzelnen Threads überschneiden sich nicht (sind eh nur jeweils 3 WCHAR-Zeiger). Überdies lese ich innerhalb der ThreadProc nur von diesen Adressen.
    Jo, so sieht das bisher aus. Ich hab auch noch keine Fehlermeldungen während der Laufzeit bekommen. Ich stelle mir den Umgang mit Threads und dem Speicher so vor:

    Alle Threads teilen sich den gleichen Heap. Wenn sich Threads aber auch die gleichen Informationen auf dem Heap teilen, muss man eben CriticalSections verwenden.

    Ist diese Vorstellung richtig?

    Eine zweite Frage hätte ich interessenhalber da noch:

    Der TLS ist eine vom Betriebssystem extra bereitgestellter Threadspezifischer Speicherbereich. Wenn man den nicht explizit anfragt, speichert man da auch nichts.

    Ist das also sozusagen ein Bereich auf dem Heap, der nur für den Thread reserviert ist, der ihn erfragt? Und wie stelle ich diesen bereit/erfrage ich ihn?



  • Original erstellt von WebFritzi:
    **Ich habe eine Threadklasse erstellt, in der die Informationen für jeden Thread gespeichert sind, und für jeden Thread wird eine Instanz davon auf dem Heap erstellt und die Members gefüllt (ebenfalls auf dem Heap). Das heißt: Die Infos der einzelnen Threads überschneiden sich nicht (sind eh nur jeweils 3 WCHAR-Zeiger). Überdies lese ich innerhalb der ThreadProc nur von diesen Adressen.
    **

    Sehr gut, dann solltest du keine Probleme haben

    **
    Jo, so sieht das bisher aus. Ich hab auch noch keine Fehlermeldungen während der Laufzeit bekommen.
    **

    Das ist leider die Tücke mit Multithreading, es mag hundertmal gut gehen und beim hundertersten mal schief 🙂 Aber wie gesagt, sieht bei dir alles sicher aus.

    **
    Ich stelle mir den Umgang mit Threads und dem Speicher so vor:
    *
    Alle Threads teilen sich den gleichen Heap. Wenn sich Threads aber auch die gleichen Informationen auf dem Heap teilen, muss man eben CriticalSections verwenden.
    *

    Ist diese Vorstellung richtig?
    **

    Exakt. Ums noch weiter zu führen teilen sich Threads fast alles, also auch globale Variablen etc. Nur Stack (damit lokale Variablen) und TLS sind strikt getrennt.

    **
    Eine zweite Frage hätte ich interessenhalber da noch:
    [quote]
    Der TLS ist eine vom Betriebssystem extra bereitgestellter Threadspezifischer Speicherbereich. Wenn man den nicht explizit anfragt, speichert man da auch nichts.
    **

    **
    Ist das also sozusagen ein Bereich auf dem Heap, der nur für den Thread reserviert ist, der ihn erfragt? Und wie stelle ich diesen bereit/erfrage ich ihn?**[/QUOTE]
    Da muss ich mal kurz nachschlagen *schweresbuchausregalzieh*. Man unterscheidet zwei sorten von TLS, dynamischen und statischen.
    Dynamischer TLS: Dieser TLS ist im Prinzip ein Array aus PVOIDs mit der Größe TLS_MINIMUM_AVAILABLE, für jeden Thread eines. Zusätzlich hält Windows pro Prozess ein Array aus booleans um zu checken welche Indizes belegt sind. Per DWORD TlsAlloc(); kann man einen Index belegen, Windows liefert den Index (oder 0xffffffff für den Fehlerfall) zurück. Dann kann jeder Thread (die Alloziierung macht man vor der Starten dre Threads) in "seinem" array per BOOL TlsSetValue(DWORD index, PVOID value); die Werte setzen und per PVOID TlsGetValue(DWORD index); wieder holen. Sclhießlich kann man per BOOL TlsFree(DWORD index) den Index wieder freigeben. So kann jeder Thread quasi ein paar daten für sich speichern.
    Statischer TLS: Hier kann ich nur für MSVC sprechen, da der laut meinem Buch per __declspec gemacht wird und ich nicht weiß, inwiefern andere Compiler sowas haben. Deklariert man eine Variable nämlich dort in dieser Form:
    __declspec(thread) DWORD meineVariable = 0;
    Dann hat jeder Thread eine eigene Kopie dieser Variablen. Da dies dann in der fertigen Win32-EXE in einem Extra-Abschnitt landet, hat vermutlich jeder Win32-Compiler eine Methode dafür. In der MSVC-Hilfe findet ischs z.B. direkt unetr "Thread local storage (TLS)".

    [ Dieser Beitrag wurde am 31.03.2003 um 02:16 Uhr von TriPhoenix editiert. ]



  • Geil! Dankeschön. 🙂 Deinen Text speichere ich mir für den Fall, dass ich sowas mal brauche. ocheinmal vielen Dank. *freu* 🙂


Anmelden zum Antworten