Tutorial
Threading
von ThePuppetMaster | Seite 4 von 5 |
Sollen nun temporäre Schreiboperationen oder Leseoperationen ausgeführt werden, kann dies mithilfe der Datenkopie erfolgen.
Ein großer Vorteil dieser Arbeitsweise ist der Schutz vor unnötiger Behinderung anderer Threads.
Es muss nur dann das Array gesperrt werden, wenn auch wirklich Informationen in das Array fließen sollen, wie z.B. in die V_State Variable.
Dieser kleine Unterschied kann erheblich zur Performance beitragen.
Ein weiterer Vorteil ist die Einsparung von Variablen. Das mag im ersten Augenblick nicht zu erkennen sein, jedoch entdeckt man solche Details meist erst beim debugen.
Wird beispielsweise ein Pixelzugriff auf die Daten nötig, muss auf dessen Pointer zugegriffen werden.
Hier schleicht sich oft ein Denkfehler ein: Man geht schlicht davon aus, das es sich hierbei um einen Pointer auf das Bild handelt, der sich nicht ändern wird.
Schließlich haben wir für jeden Thread ein eigenes Bild erzeugt auf das nur der jeweilige Thread zugreift. Jedoch dürfen wir nicht vergessen, das dieser Pointer im Array hinterlegt ist.
Es ist also nötig, das wir diesen Pointer zwischenspeichern. Dies kann man durch eine Zusätzliche Variable einfach lösen, oder über die DATEN-Kopie.
Von Vorteil ist die Datenkopie nicht in jedem Fall.
Hier muss wieder abgewogen werden was alles in das Array einfließt und welche Informationen im Array hinterlegt werden.
Sind es nur 1 oder 2 kleinen Informationen, dann ist es sicher von Vorteil 2 separate Variablen zu erzeugen und mit dem Pointer auf das Array-Element zuzugreifen, falls erforderlich.
Sollten es einmal mehr Informationen sein, die übergeben werden, ist die Nutzung einer Datenkopie von weit größerer Relevanz.
Als Beispiel können wir hier das vorzeitige beenden des Threads (wie oben kurz erwähnt) demonstrieren.
Wird das Programm abgebrochen, muss dafür gesorgt werden, das die Threads ihre Arbeit vorzeitig abbrechen.
Gehen wir davon aus, das ein Thread Pixelweise arbeitet
Sub Bearbeitugnsthread(V_Data as Any Ptr)
'...
'sind die Daten valid, dann kann weiter gearbeitet werden
For Y as UInteger = 1 to 20
For Y as UInteger = 1 to 20
'Pixelverarbeitung
'...
Next
Next
End Sub
Der Einfachste Fall diese Schleife vorzeitig zu beenden, ist die Überwachung der Statusvariable (V_State).
Sub Bearbeitugnsthread(V_Data as Any Ptr)
'...
'sind die Daten valid, dann kann weiter gearbeitet werden
For Y as UInteger = 1 to 20
For Y as UInteger = 1 to 20
'Pixelverarbeitung
'...
MutexLock(XMutex)
If Info->V_State = 100 Then
Info->V_State = 255
MutexLock(XMutex)
Exit Sub
Else: MutexLock(XMutex)
End If Next
Next
End Sub
Der fatalen Nachteil an dieser Vorgehensweise ist schnell zu erkennen. Arbeitet die Schleife schnell, kann sie die Threads untereinander ausbremsen.
Eine einfache aber effektive Methode das zu verhindern ist eine zeitlich geregelte Prüfung.
Da das erzwungene Ende eines Threads keineswegs zeitkritisch ist, muss auch nicht explizit jedes Mal untersucht werden, ob ein "Exit" nötig ist.
Führen wir eine Variable ein, die eine Art "zeitlichen Puffer" definiert, können wir die Prüfung z.B. jede Sekunde ausführen. Das ist zwar immer noch relativ schnell, jedoch absolut legitim.
Es beschleunigt nicht nur den Ablauf des Threads, sondern das gesamte Programm erheblich.
Sub Bearbeitugnsthread(V_Data as Any Ptr)
'...
'sind die Daten valid, dann kann weiter gearbeitet werden
Dim XTot as Double 'Variable für einen Zeitstempel
For Y as UInteger = 1 to 20
For Y as UInteger = 1 to 20
'Pixelverarbeitung
'...
If XTot < Timer() Then 'Ist der Zeitstempel in der Vergangenheit, dann Prüfung durchführen
MutexLock(XMutex)
If Info->V_State = 100 Then
Info->V_State = 255
MutexLock(XMutex)
Exit Sub
Else: MutexLock(XMutex)
End If
XTot = Timer() + 1 'erst NACH der Prüfung den Zeitstempel neu setzen.
End If
Next
Next
End Sub
Hierbei muss beachtet werden, das der neue Zeitstempel erst NACH der Prüfung wieder gesetzt wird. Würde man dieser gleich nach dem "If" ausführen, könnte eine zu lange Wartezeit im ThreadLock(), zu einer zu kurzen Zykluslaufzeit führen.
Dies würde zwar die Prüfzeit von einer Sekunde erhalten, jedoch das Threadingmodell und damit den Geschwindigkeitsvorteil wieder zunichte machen. Durch das späte setzen des neuen Stempels wird sich der Intervall nur minimal anheben.
Da die primäre Aufgabe des Programms jedoch nicht das abbrechen seiner Funktion ist, sollte diese Vorgehendweise durchaus vertretbar erscheinen.
Damit nun ein Abbruch erfolgen kann, muss natürlich allen Threads mitgeteilt werden, das es nun Zeit ist, sich dem Ende zu nähern.
MutexLock(XMutex)
Array(123).V_Status = 100
MutexUnLock(XMutex)
Zusätzliche Informationen und Funktionen | |||||||
---|---|---|---|---|---|---|---|
|
|