LB_GETCOUNT reagiert wie ein blocking call...
-
Blos nicht - die bessere Lösung ist es, über Events oder ähnliches den Threads zu sagen, daß sie ihre Arbeit beenden sollen, und dann mit WaitForMultipleObjects() darauf warten, daß alle fertig sind.
(TerminateThread ist eine Notfalllösung für den Fall, daß der Thread dir dein Betriebssystem zerhackstückt)
-
Aber wie können die ihre Arbeit beenden, ohne ein Abbruchkriterium in einer Schleife? Denn es muss ja verhindert werden, dass wenn das Programm schließt, der Nebenthread noch einmal durchläuft. Oder muss ich vor jedem SendMessage() FindWindowEx() aufrufen (Wäre ja auch nicht 100% sicher!?) ?
MfG
-
Indem du ihnen ein Abbruchkriterium gibst (gut macht sich da "WaitForSingleObject(endeEvent,0)==WAIT_TIMEOUT"). Die Nachrichtenschleife lebt durch den Wait...() Aufruf im Hauptprogramm noch lange genug, auch wenn die Nachrichten eventuell nicht mehr ausgewertet werden.
Aber der Nebenthread sollte dann statt SendMessage() lieber PostMessage() oder SendMessageTimeout() verwenden, um das Hauptprogramm über Neuigkeiten zu informieren, sonst bekommst du einen erstklassischen Deadlock (der Thread wartet darauf, daß das Hauptprogramm seine Nachricht verarbeitet, das Hauptprogramm wartet darauf, daß der Thread sich beendet).
-
Hey!
Mit...
SendMessageTimeout(listHandle, LB_ADDSTRING, 32, reinterpret_cast<LPARAM>("blatext"), SMTO_ABORTIFHUNG, 1, 0)...haut es nun hin. Die Reaktion auf WM_DESTROY sah schon immer so aus:
if(threadHandle) WaitForSingleObject(threadHandle, INFINITE); CloseHandle(threadHandle); PostQuitMessage(0);Eigentlich sollte hier doch sowieso gewartet werden, bis der Nebenthread fertig ist, und dann erst die Nachrichtenschleife & Fenster zerstört werden?!
Danke!
MfG
-
ceplusplus@loggedoff schrieb:
Hey!
Mit...
SendMessageTimeout(listHandle, LB_ADDSTRING, 32, reinterpret_cast<LPARAM>("blatext"), SMTO_ABORTIFHUNG, 1, 0)...haut es nun hin.
Meinst du nicht, daß ein Timeout von einer Millisekunde im aktiven Dienst ein wenig knapp bemessen ist? Wenn du Pech hast, kommt die Nachricht gerade während einer etwas längerfristigen Tätigkeit des Hauptprogramms.
Eigentlich sollte hier doch sowieso gewartet werden, bis der Nebenthread fertig ist, und dann erst die Nachrichtenschleife & Fenster zerstört werden?!
Ja, das war auch korrekt - nur während du dort gewartet hast, blieben die Nachrichten des Thread in der Warteschlange hängen.
-
Oh, hmm stimmt! Also bin ich gezwungen, ein Timeout zu setzen?
SendMessageTimeout() funktioniert leider doch nicht wie gewollt:SendMessageTimeout(listHandle, LB_GETCOUNT, 0, 0, SMTO_ABORTIFHUNG, 1000, 0);Gibt immer 1 zurück, SendMessage() hingegen arbeitet korrekt. Warum hat PostMessage() usw. eigentlich keinen Effekt bei mir (Gibt bei LB_GETCOUNT auch immer 1 zurück und LB_ADDSTRING zB. hat gar keinen Effekt) ?
Danke!
MfG
-
Die Rückgabewerte von PostMessage() und SendMessageTimeout() sind nicht die Daten, die die Behandlungsfunktion geliefert hat. Bei PostMessage() kannst du keine Rückmeldung bekommen, weil die Nachricht ja noch unterwegs sein dürfte. Bei SendMessageTimeout kannst du als letzten Parameter eine DWORD-Variable, wo die Antwort im Erfolgsfall reingeschrieben wird:
DWORD answer,result; result = SendMessageTimeout(listHandle,LB_GETCOUNT,0,0,SMTO_ABORTIFHUNG,1000,&answer); if(result==0) { //Fehler oder Timeout } else { //Erfolg: TRACE("Count returned: %d\n",answer); }(PostMessage() mit LB_ADDSTRING hat ein anderes Problem - der übergebene String ist möglicherweise schon ungültig, bevor das Zielfenster die Nachricht auswertet)
-
Hey!
Danke, meine Voreiligkeit

Hätte es gerne irgendwie ohne Timeout gelöst, also falls wem noch was einfällt, bitte!
MfG
-
Es gibt auch noch SendMessageNotify() und SendMessageCallback() als Alternativen (die aber beide nicht mit Zeigern umgehen können - das selbe Problem wie bei PostMessage()).
Aber was genau hast du eigentlich gegen Timeout? Die Angabe dort bedeutet doch nicht, daß die Funktion immer 1 Sekunde wartet, bevor sie abbricht - das ist die maximale Wartezeit. (und im Normalbetrieb liefert sie genauso zuverlässig eine Antwort wie SendMessage())
-
Naja, die Anwendung läuft dann eben nach Beenden noch eine Zeit lang weiter, wenn ich im Nebenthread oft SendMessageTimeout() aufrufe, kommen schon mal 10 Sekunden oder mehr zusammen. Find ich nicht so toll.
Was meinst du mit "kann nicht mit Zeigern umgehen"? Dass ich zB. nicht LB_GETCOUNT verwenden kann? Denn wenn diese Funktionen sofort zurückkehren, und die Nachricht noch nicht verarbeitet wurde, wo soll dann das Ergebnis sein?
MfG
-
ceplusplus@loggedoff schrieb:
Naja, die Anwendung läuft dann eben nach Beenden noch eine Zeit lang weiter, wenn ich im Nebenthread oft SendMessageTimeout() aufrufe, kommen schon mal 10 Sekunden oder mehr zusammen. Find ich nicht so toll.
Da wäre es auch eine gute Idee, die Bedingung "Timeout wurde ausgelöst" als Abbruchbedingung des Threads zu verwenden - so daß du nur einen einzigen fehlgeschlagenen Aufruf hast (und eine Sekunde Wartezeit sollte akzeptabel sein).
Was meinst du mit "kann nicht mit Zeigern umgehen"? Dass ich zB. nicht LB_GETCOUNT verwenden kann? Denn wenn diese Funktionen sofort zurückkehren, und die Nachricht noch nicht verarbeitet wurde, wo soll dann das Ergebnis sein?
Nein, damit meinte ich eher das Problem, was ich oben mit LB_SETTEXT angesprochen hatte - weil die Funktionen sofort zurückkehren, sind die übergebenen String-Daten womöglich nicht mehr gültig, wenn das Ziel endlich zur Verarbeitung kommt.
(hast du zufällig die MSDN in Reichweite? Wenn ja, empfiehlt sich ein Blick in die Funktionsbeschreibungen - speziell die "Remarks" Sektion ist immer wieder aufschlußreich)
-
Aber zur Abbruchbedingung kommt der Thread immer erst nach mehreren Aufrufen von SendMessageTimeout...
Oder soll ich einfach vor jedem dieser Aufrufe prüfen, ob exitThread nicht schon TRUE ist, und gegebenfalls returnen...?!
MSDN ist mir nicht fremd, ich bin aber einfach davon ausgegangen, dass die *Message*- Funktionen gleich funktionieren, sry.
MfG
-
Wenn Du SendMessage (auch SendMessageTimeout) über Threadgrenzen hi9nweg verwendest, hast Du von Deinem Multithreading garnichts mehr, alles wird synchronisiert, bis die Nachrichten abgearbeitet worden sind, als ob Alles in einem Thread lääääuft.
Lass SendMessage aus einem Thread in einen anderen einfach bleiben!
-
Geht nicht!
Mein Programm soll doch reagieren, während es beschäftigt ist:
- ListBox eines fremden Fensters auslesen
- Daten verarbeiten
- 1 Sekunde Warten (Sleep())
und wieder von vorn...Es soll nicht 100x in der Sekunde diese Aufgabe tun, sondern sekundenweise (1. wegen Prozessorlast, 2. muss es die Aufgabe gar nicht so oft tun). Während dem Sleep() würde das GUI doch nicht mehr reagieren...
Wenn ich einen weiteren Thread erstelle, und dieser eine Sekunde "schläft", reagiert währenddessen das GUI... deshalb der zweite Thread.
Was gibt es noch für Möglichkeiten?
Danke!
MfG
-
Warum musst Du die Daten aus der Listbox auslesen. Halte die Daten in einer eigenen Struktur parallel und schon hast Du kein Problem mehr.
Lass das Fenster außen vor und arbeite mit den Daten!
-
ceplusplus@loggedoff schrieb:
- ListBox eines fremden Fensters auslesen
MfG
Ich werde wohl einen Windows Timer verwenden, der jede Sekunde die Auslese- und Verarbeitungsaufgabe aufruft, aber da ist noch ein anderes Problem:
Das Programm soll per Winsock fernsteuerbar sein.Die Probleme, ohne einen zusätzlichen Thread zu erstellen:
- listen() geht schonmal nicht, da es blockiert und somit auch das GUI
- select() geht nicht, weil ich nicht 100% Prozessorauslastung möchte, und Sleep(1) möchte ich nicht einbauen weil sich dann das GUI beim maximieren so langsam aufbaut...Was soll ich nur tun?
MfG
-
- listen() geht schonmal nicht, da es blockiert und somit auch das GUI
du meinst accept!

-
Jo wahrscheinlich, weiß ich ned so genau. Jedenfalls blockiert's :p
Es werden ferngesteuert auch GUI elemente verändert...
Ich weiß nicht, wie ich das alles nun am elegantesten lösen kann...
-
Während dem Sleep() würde das GUI doch nicht mehr reagieren...
Ich hab nicht den ganzen Thread hier gelesen, ... aber warum nicht einfach mit SetTimer() & WM_TIMER?
-
Jo, ist mir auch in den Sinn gekommen. Bin aber blöd, geht nämlich nicht, weil:
Ich schreibe in ein fremdes Edit und lese dann eine fremde ListBox aus. Nach dem schreiben ins Edit muss ich etwa eine halbe Sekunde warten, bis das Programm die ListBox entsprechend gefüllt hat, dann lese ich die ListBox aus und dann muss ich bis zu 64x wieder in das Edit schreiben und bei jedem Mal ein bisschen warten, bis die Information in der ListBox auftaucht...
Also:
...
- Befehl ins Edit
- 500ms warten
- ListBox auslesen
- Befehl ins Edit
- 1000ms warten
- ListBox auslesen
- Befehl ins Edit
- 500ms warten
- ListBox auslesen
- Befehl ins Edit
- 500ms warten
- ListBox auslesen
...In jedem Fall würde also das GUI blockieren, weil ich eben warten muss, bis das fremde Programm auf die Edit-Eingaben reagiert und seine ListBox füllt..
MfG