Erstellung eines Worker-Threads zur Grafikausgabe
-
Dann lies dir mal den Remarks Abschnitt durch.
-
@elmut19 sagte in Erstellung eines Worker-Threads zur Grafikausgabe:
Da ich ausschliesslich mit Membern meiner "CViewGrafik" arbeite, die anschliessend eh behandelt werden,
kann hier nichts passieren.Falsch.
-
@DocShoe sagte in Erstellung eines Worker-Threads zur Grafikausgabe:
Dann lies dir mal den Remarks Abschnitt durch
Die Remarks habe ich gelesen, auch vorher schon.
Ich sehe ein, dass es eine heikle Sache ist.
Die 4 Punkte konnte ich allerdings positiv beantworten.Jedenfalls muss ich sicherstellen, dass ich den Thread loswerde!
Und das muss auch ohne Beeinträchtigung des Anwenders erfolgen.@hustsbear
Aber was ist noch falsch?
Es ist auch sichergestellt, dass das Thread-Handle geschlossen wird.
Ich brauche eine Möglichkeit, den Thread nach einer kurzen Zeit zu 100% loszuwerden.
Ein "WaitFor..(... INFINITE)" ist keine Lösung!
Ein WaitFor..(... ZWEI_SEKUNDEN) wäre angemessen.
Das kann ich über den Event am Thread-Ende gewährleisten.
Und das ist auch drin.
Und über das Flag, das ich an den Thread sende, wird dieser auch beschleunigt abgebrochen.Aber irgendeine Sicherheit muss ich noch behalten.
-
@elmut19 sagte in Erstellung eines Worker-Threads zur Grafikausgabe:
@hustsbear
Aber was ist noch falsch?Na der Satz den ich zitiert habe:
Da ich ausschliesslich mit Membern meiner "CViewGrafik" arbeite, die anschliessend eh behandelt werden,
kann hier nichts passieren.Du rufst da drin ja Win32 und MFC Funktionen auf. Diese Funktionen ... machen Dinge. Und wenn sie z.B....
- diese Dinge zumindest teilweise im Usermode machen und
- dazu Locks (Critical Sections, SRWLocks, ...) verwenden
dann kann dir das übel um die Ohren fliegen. (Nur damit das klar ist: Das ist nicht die einzige Möglichkeit wie es zu einem Problem kommen kann, es ist nur ein Beispiel.)
Wenn du einen Thread mit
TerminateThread
abschiesst, dann kannst du nicht kontrollieren wo er abgebrochen wird. D.h. er könnte z.B. eine Critical Section gelockt haben. Die bleibt dann gelockt und dein Programm wird halt einfach hängen bleiben sobald die nächste Funktion aufgerufen wird die die selbe Critical Section locken muss.Also ist die Schlussfolgerund es "kann hier nichts passieren" falsch. Es kann sehr wohl was passieren.
Ich brauche eine Möglichkeit, den Thread nach einer kurzen Zeit zu 100% loszuwerden.
Ein "WaitFor..(... INFINITE)" ist keine Lösung!Und genau das ist auch wieder falsch. Ein
WaitFor..(... INFINITE)
ist genau die Lösung. Du musst halt sicherstellen dass der Mechanismus den du verwendest um den Thread dazu zu bringen sich selbst zu beenden zuverlässig ist.Ein WaitFor..(... ZWEI_SEKUNDEN) wäre angemessen.
Nein! Ich verstehe ja deine Sorge, vor vielen Jahren als ich selbst das erste mal mit diesem Problem konfrontiert war hab ich mir das selbe gedacht. Und die Versuchung ist gross hier ein "Not-Aus" einbauen zu wollen. Nur glaub mir bitte: es ist besser es nicht zu tun. Wenn sich der Thread nicht von selbst beendet, dann hat dein Programm einen Fehler. Den Thread nach ein paar Sekunden abzubrechen macht aber alles nur noch schlimmer. Es maskiert den Fehler, mit einer "Lösung" die die unangenehme Eigenschaft hat selbst wieder Probleme erzeugen zu können. Und noch dazu Probleme die man dann kaum festnageln kann.
Was du machen kannst wenn du wirklich meinst es sei notwendig: Wenn der Thread sich nach ein paar Sekunden immer noch nicht selbst beendet hat, dann beende einfach den ganzen Prozess. Idealerweise schreibst du vorher noch einen Crash-Dump damit du nachher was hast womit du schauen kannst warum der Thread sich nicht beendet hat: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/nf-minidumpapiset-minidumpwritedump
-
Weiter oben habe ich ja schon vorgeschlagen, die Abbruchbedingung in der Threadfunktion häufiger zu prüfen, und nicht nur bei jedem Schleifendurchlauf. Die häufige Überprüfung kostet zwar etwas Performance, weil jedes Mal eine CriticalSection betreten werden muss, aber damit reagiert der Thread zügiger auf die Abbruchbedingung. Wenn der Threadabbruch zu träger wird musst du halt die Intervalle zur Überprüfung der Abbruchbedingung verkürzen.
-
@DocShoe sagte in Erstellung eines Worker-Threads zur Grafikausgabe:
Die häufige Überprüfung kostet zwar etwas Performance, weil jedes Mal eine CriticalSection betreten werden muss, aber damit reagiert der Thread zügiger auf die Abbruchbedingung.
Wozu eine CriticalSection?
std::atomic<bool>::load(std::memory_order_acquire)
ist völlig ausreichend. Und das ist auf x86 ein einfacher, billiger Speicherzugriff.
(Meistens wird sogarstd::memory_order_relaxed
reichen, aber man muss ja nicht übertreiben.)
-
Ich kenn mich mit dem C++11 Synchronisierungskram nicht aus, unsere Software ist älter und es gibt eigene Wrapper für die Win32 Objekte. Damit sind wir bisher gut gefahren und sehen atm keinen Grund zur Umstellung.
Und ja, ich müsste mich mal mit den C++11 Neuerungen beschäftigen. Mehr gibt unser Compiler leider nicht her.
-
@DocShoe
Ich arbeite zwar für mich selbst inzwischen mit VS2019.
Aber für unser Kunden wird immer noch die exe mit VS2005 erstellt.
Es ist einfach keine Zeit, die ganze Installation umzustellen und wieder neue Libs mit zu verteilen.
-
@elmut19
Auf was genau beziehst du dich?
-
@DocShoe Vermutlich darauf dass Visual Studio 2005 kein C++11 kann
@elmut19 Du kannst auch Boost.Atomic verwenden.
Bzw. wenn's dich nicht stört dass es nicht zu 100% vom C++ Standard abgedeckt ist sondern nur von einer zusätzlichen Garantie von Visual Studio, dann kannst du für sowas wie ein Cancel-Flag auch einfach ein
volatile bool
verwenden. VS 2005 garantiert beivolatile
Variablen mit passendem Alignment dass:- Lese und Schreibzugriffe immer atomar sind
- Lesezugriffe immer "acquire" Semantik haben
- Schreibzugriffe immer "release" Semantik haben
(Einschränkung: die Garantie dass Zugriffe atomar sind steht dort nicht explizit und gilt auch nur für bestimmte Typen. Also z.B. nicht für structs.)
In neueren VS Versionen ist diese Garantie abhängig vom
/volatile
Switch: https://docs.microsoft.com/en-us/cpp/build/reference/volatile-volatile-keyword-interpretation?view=msvc-160
-
@DocShoe
Ja, beim Sprachstandard bin ich einfach noch etwas hinterher.
Und nun noch BOOST einzubauen, schient mir auch nicht so sinnvoll.
Es gibt auch so noch viel Potential für ein Reengineering.
Zumindest eine der Grafiken habe ich auch durch weglassen mehrfacher identischer Punkte um ca. 50% schneller bekommen