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
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
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)