Seite 1 von 1

Threads: Zugriff auf strukturierten Speicher

Verfasst: 28.02.2019 21:52
von Kurzer
Hallo,

ich habe eine Frage bzgl. des Zugriffs auf ein und die selbe Instanz eines Strukturspeichers aus mehreren Threads heraus. In meinem Fall geht es um ein Customgadget (Kurvendiagramm-Anzeige), welches unter anderem diverse Setter-Prozeduren anbietet. Das Gadget hält seine Daten in einer Struktur im Speicher.

Es erfolgen dort Zugriffe nach folgendem Schema:

Code: Alles auswählen

With *GraphGadget
	\stBuffer[iBufferNumber]\iBufferShowGrid = iBufferShowGrid
	\stBuffer[iBufferNumber]\iBufferGraphGridSize = iBufferGraphGridSize
	\stBuffer[iBufferNumber]\iBufferGraphGridColour = iBufferGraphGridColour
	; ... usw.
EndWith
Nun rufe ich diese Setter-Prozeduren (SetBufferAddress(), SetBufferOffset() usw.) periodisch aus einem Thread heraus auf und habe gleichzeitig ein paar Testbuttons im Main() laufen, die diese Prozeduren ebenfalls aufrufen.

Ich habe das Testprogramm ohne die Compilerenstellung "Threadsave" laufen und beim Herumklicken mit den Buttons sporadische Speicherzugriffsfehler festgestellt. Offenbar immer dann, wenn Thread und Main() gleichzeitig auf die Struktur zugreifen.

Nun habe ich alle Prozeduren, die auf den Strukturspeicher des Gadgets zugreifen wie folgt abgesichert (ich wollte dafür nicht extra einen Mutex() bemühen):

Code: Alles auswählen

; Wait until the Gadget is unlocked
While *GraphGadget\iGadgetLocked = #True : Delay(1) : Wend
*GraphGadget\iGadgetLocked = #True
With *GraphGadget
	\stBuffer[iBufferNumber]\iBufferShowGrid = iBufferShowGrid
	\stBuffer[iBufferNumber]\iBufferGraphGridSize = iBufferGraphGridSize
	\stBuffer[iBufferNumber]\iBufferGraphGridColour = iBufferGraphGridColour
	; ... usw.
EndWith		
*GraphGadget\iGadgetLocked = #False
Bisher habe ich keine Speicherfehler mehr festgestellt und gehe davon aus, dass meine Vermutung mit der Kollision beim Zugriff auf den Strukturspeicher richtig war.

Aber ich frage lieber nochmal nach: Ist es richtig, dass eine Exe abschmieren kann, wenn mehrere Threads (oder ein Thread und main() ) gleichzeitig auf einen strukturierten Speicherbreich zugreifen? Bisher dachte ich, dass dies nur bei Verwendung von Strings Probleme bereitet.

Und kann man das so lösen wie ich es getan habe (*GraphGadget\iGadgetLocked = #True)?

Nachtrag: Kann es sein, dass ein Mutex quasi genau das macht was ich oben zu Fuß mache? Ich habe keine Ahnung wie ein Mutex intern realisiert wird.

Nachtrag 2: Ich habe die Prozeduren jetzt mit einem Mutex gelocked. Auch hier keine Speicherfehler mehr und obendrein weniger Codezeilen. Ich gehe mal davon aus, das ein Mutex intern nicht viel mehr Ressourcen verbraucht als meine vorherige "zu Fuß" Lösung.

Code: Alles auswählen

; Wait until the Gadget is unlocked
LockMutex(*GraphGadget\iGadgetMutex)

;... some code		
		
UnlockMutex(*GraphGadget\iGadgetMutex)

Re: Threads: Zugriff auf strukturierten Speicher

Verfasst: 28.02.2019 22:47
von ts-soft
Wenn ein Thread auf den Speicher zugreift, wird er für weitere Threads gesperrt, was leider nicht ausreicht, weil wenn 2 oder mehrere Threads auf den Speicher zugreifen (quasi "zeitgleich"), ist es zu spät zum sperren weiterer Threads, weil dann ist es schon passiert.

Es ist also die CompilerOption Threadsafe (vor allem für Strings) sowie ein Mutex erforderlich! Alles andere führt früher oder später zu Fehlern. Es kommt auch nicht drauf an, wie wahrscheinlich so ein Fehler ist, sondern er ist grundsätzlich auszuschließen. Murphy läßt grüßen :mrgreen:

Re: Threads: Zugriff auf strukturierten Speicher

Verfasst: 01.03.2019 00:17
von Kurzer
Alles klar, dann bin ich ja mit meiner letzten Version (mit Mutex) schon auf dem richtigen Weg gewesen. Fehlt dann nur noch die Option "Threadsafe" in den Compilereinstellungen. :allright: