Wie richtig auf Botschaften warten
-
Das stellt doch alles kein Problem dar. Wichtig ist lediglich die Frage, weiß dein Workingthread immer, oder zumindest manchmal, wo er sich prozentual gerade befindet? Wenn ja, dann schickt er eben eine Message PostMessage(Hauptfenster, WM_COMMAND, (WPARAM)CMD_BINISCHGERADEDA, (LPARAM)x) wobei x eine Prozentangabe ist und der Eventhandler des Hauptfensters erhöht dann z.B. den Wert einer Progressbar oder sonst irgendeine Ausgabe.
Diese Aussage versteh ich nicht:
AntonWert schrieb:
Zur Ergänzung: Das Hauptprogramm hat eine sehr lange Schleife in der ein Thread erzeugt - abgearbeitet - und dann mit dem nächsten Schleifendurchlauf fortgefahren wird. Das Problem ist nun, das das Hauptprogramm irgendetwas machen muss solange der tread arbeitet, nur was....?
Für was braucht das Hauptprogramm eine sehr lange Schleife. Meiner Meinung nach sollte alles was die Bedienung der Fenster, Buttons oder sonstwas in einer Winapi Anwendung beeinträchtigt in einen extra Thread, dann kannst du dein Programm immer noch gut bedienen. Das geht natürlich zu Lasten der Performance. Vieleicht erklärts du mal genauer was genau dein Programm machen soll, möglicherweise gibt es ja alternative Lösungsansätze.
-
Das Programm verarbeitet den Inhalt von Dateien. Also einlesen, Berechnungen anstellen und ggf. neue Datei schreiben. Diese Aktionen führt ein separater Thread aus. Er weis auch (zumindest so genau wie nötig) vieviel Prozent er von der Datei bereits bearbeitet hat.
Das Hauptprogramm "kennt" den Speicherort der Dateien. Per Button-Click startet eine Schleife mit FindFirstFile / FindNextFile und sucht nach Diesen Dateien (das sind unter umständen mehrere tausend Stück). Somit ist mein Hauptprogramm aber in dieser Schleife "gefangen"

Mit Absicht habe ich nicht alle Dateien in eine Liste eingelesen, denn a) könnte die Liste sehr sehr lange werden was den Speicherverbrauch dann unnötig erhöht, und b) könnte sich der Inhalt im laufe der Verarbeitung noch ändern.
Hoffe das hilft weiter.
-
Die Antwort wurde die schon gesagt. Nimm eine Message Loop!
Die Prozessorlast wird bei einer GetMesssage/TranlateMessage/DispatchMessage Schleife nur dann extrem ansteigen, wenn dieser Thread oder ein Fenster mit Nachrichten bombardiert wird.Wenn Du 100% Auslastung hast, kann dies ja auch an Deinem Workerthread liegen.
-
AntonWert schrieb:
Das Hauptprogramm "kennt" den Speicherort der Dateien. Per Button-Click startet eine Schleife mit FindFirstFile / FindNextFile und sucht nach Diesen Dateien (das sind unter umständen mehrere tausend Stück). Somit ist mein Hauptprogramm aber in dieser Schleife "gefangen"
Starte einen weiteren Thread für die Suche nach den Dateien, so daß sich das Hauptprogramm ausschließlich um die GUI kümmern kann.
-
AntonWert schrieb:
Das Hauptprogramm "kennt" den Speicherort der Dateien. Per Button-Click startet eine Schleife mit FindFirstFile / FindNextFile und sucht nach Diesen Dateien (das sind unter umständen mehrere tausend Stück). Somit ist mein Hauptprogramm aber in dieser Schleife "gefangen"

Warum startet dein Hauptprogramm, nicht einen Workingthread der sowohl das Finden, als auch das Auswerten der Dateinen übernimmt. Solange die Auswertung stattfindet, braucht doch eigentlich keine neue Datei gefunden werden, die verarbeitet werden muß. Erst wenn die Datei verarbeitet wurde, macht er sich auf die Suche nach einer weiteren Datei die deinem Kriterium entspricht. Das würde dann auch wieder deinern Aussage "könnte sich der Inhalt im laufe der Verarbeitung noch ändern." entgegen kommen. Solange der Working-Thread arbeitet, deaktiviert du den Button für die Suche und aktivierst vieleicht einen Button für "Abbrechen" der eine globale Variabele setzt. Diese Variable kannst du dann im Workingthread an verschiedenen Programmstellen abfragen und den Workingthread sauber beenden.
-
@Helmut:
Diese Idee hatte ich mir schon öfters überlegt, aber dennoch verworfen.
Ich würde z.B. die aktuelle Datei welche bewarbeitet wird anzeigen, und die kann ich irgendwie ja nicht durch eine Windows-Botschaft schicken - oder geht sowas? Mein Hauptprogramm kann ja bereits auf Botschaften des Threads hören, aber das sind eben nur "int"-Daten.
-
Du könntest den Namen in einem Feld ablegen und über eine Critical-Section ablegen. Du könntest dann eine Nachricht senden, die über die Änderung den Main-Thread informiert.
-
Ja das geht, du kannst z.B. in deiner WM_COMMAND Message für LPARAM einen Pointer auf CHAR schicken und dein Eventhandler wertet diesen aus und zeigt den String an (beachte hierbei ob der String Null terminiert ist).
Oder du legst dir eine globale Struktur an. Dein Workingthread füllt diese Struktur mit Informationen über den momentanen Zustand, z.B. Dateiname, Dateigröße, Dateiinhalt, Protzentangabe und was immer du da noch reinpacken möchtest. Dann musst du nicht mal einen Pointer mit WM_COMMAND mitschicken, weil die Struktur ja global ist. Es empfield sich dann ein Flag einzubauen, das vom Hauptthread gesetzt wird wenn dieser die Nachricht erhalten hat, wenn der Hauptthread das Flag noch nicht gesetzt hat, dann gilt für den Workingthread, daß die Struktur schreibgeschützt ist. Dies wäre eine Möglichket.
Wenn du aber kein Freind von globalen Variablen bist, dann kannst du die Struktur in deinem Workingthread anlegen und einen Pointer auf die Struktur über WM_COMMAND schicken.
-
@*helmut*
1. Muss man dazu keine WM_COMMAND Nachricht verwenden. Besser eine eigene definierte Nachricht (WM_APP+x oder RegisterMessage)
2. Sollte man bei Zeigern nur SendMessage verwenden, PostMessage geht nicht, denn man kann nicht für die Gültigkeit des Zeigers garantieren.
3. SendMessage hat den Nachteil einer erzwungenen Threadsynchronisation.Ich würde einen Storage reservieren und diesen mit einer Ctrical Section absichern.
-
Hallo,
ich hab für mich nun eine Lösung gefunden. Die Idee mit der globalen Struktur find ich in diesem Fall am bessten.
Der Thread legt die aktuellen Informationen in die Struktur, das Hauptprogramm erstellt daraus eine brauchbare Anzeige.Vielen Dank für die Hilfen.
-
Nur noch mal als Anmerkung:
Da lesend und schreibend auf die Daten zugegriffen werden musst Du diese über eine Ctrical Section absichern.
-
Martin Richter schrieb:
Nur noch mal als Anmerkung:
Da lesend und schreibend auf die Daten zugegriffen werden musst Du diese über eine Ctrical Section absichern.Dazu hab ich eine Frage. Muß so eine Situation immer über eine Critical Section abgesichert werden, oder kann man davon ausgehen, dass bei diesem Anwendungsfall (nur eine Prozentangabe die durch des Hauptthread aktualisiert wird) es auch zuverlässig ohne eine Critical Section realisiert werden kann?
Was kann in dem konkreten Fall passieren, wenn die Schreib-/Lesebereiche nicht über eine Critical Section abgesichert werden. Einen Deadlock zum Beispiel kann ich mir erst mal nicht vorstellen.
-
daimonion schrieb:
Martin Richter schrieb:
Nur noch mal als Anmerkung:
Da lesend und schreibend auf die Daten zugegriffen werden musst Du diese über eine Ctrical Section absichern.Was kann in dem konkreten Fall passieren, wenn die Schreib-/Lesebereiche nicht über eine Critical Section abgesichert werden.
Der lesende Thread kann inkonsistente Daten bekommen, weil der schreibende Thread nach dem Schreiben eines Teils der Daten unterbrochen werden kann.
-
Solange es sich nur um einen einzigen 32bit Wert handelt ist dies wohl ausgeschlossen...
-
Belli schrieb:
Der lesende Thread kann inkonsistente Daten bekommen, weil der schreibende Thread nach dem Schreiben eines Teils der Daten unterbrochen werden kann.
Okay, das macht Sinn, wenn mehrere Daten geschrieben werden. Danke für die Antwort.