SendMessage() aus mehreren Threads
-
Hallo,
ich bin gerade dabei, mich etwas mit WinHTTP zu beschäftigen. In ein Textfeld sollen zuerst beliebige URLs eingetragen werden, deren Quelltexte das Programm dann abruft und nacheinander im selben Textfeld ausgibt.Ich habe dazu den "asynchronen" Modus aktiviert und stelle dann für jede eingegebene URL eine entsprechende GET-Anfrage. Sobald ich in der Callback-Funktion darüber informiert werde, dass alle Daten eines Requests abgerufen wurden, möchte ich diese zum bereits vorhandenen Inhalt der Textbox anfügen, sodass sich am Ende eigentlich alle Quelltexte hintereinander dort befinden müssten.
Zum Anfügen verwende ich folgende Helperfunktion, da die WinAPI sowas leider nicht von Haus aus mitbringt:
void editCtrlAppend(HWND hEdit, LPCTSTR szText) { int length = GetWindowTextLength(hEdit); SetFocus(hEdit); SendMessage(hEdit, EM_SETSEL, (WPARAM) length, (LPARAM) length); SendMessage(hEdit, EM_REPLACESEL, 0, (LPARAM) szText); }Zum eigentlichen Problem: Es wird leider immer nur der zuletzt empfangene Quelltext angezeigt, obwohl die obige Funktion für jeden fertigen Request einmal aufgerufen wird. Mit dem Debugger habe ich herausgefunden, dass die Abfrage nach der Länge des bereits in der Textbox befindlichen Textes (Zeile 3) immer 0 ergbt, obwohl sich doch (außer beim ersten Mal) bereits Text darin befinden müsste.
Obwohl (oder gerade weil) ich mit Threads bisher so gut wie nichts gemacht habe, vermute ich, dass es damit zusammenhängt, denn es wird ja bei solchen asynchronen Verbindungen anscheinend das Polling in einen Thread verlegt, damit der Hauptthread (und damit die Anwendung) währenddessen nicht blockiert.
-
das hat nix mit threads zu tun. asynchron i/o callbacks wird mit apc gemacht. zu dem prob, hast bestimmt das falsche handle benutzt und was sagt GetLastError.
-
Vielen herzlichen Dank, ich habe natürlich gar nicht erst an die Möglichkeit gedacht, hier GetLastError zu verwenden
(ich dachte auch, dass es bei fehlerhaftem Handle einen Absturz geben müsste). Ergebnis war jedenfalls wie von dir vermutet 1400. 
Und der Grund: In Anlehung an das MSDN-Tutorial zu diesem Thema habe ich folgende Struktur definiert:
typedef struct { HWND hWindow; // Handle for the dialog box HINTERNET hConnect; // Connection handle HINTERNET hRequest; // Resource request handle DWORD dwSize; // Size of the latest data block DWORD dwTotalSize; // Size of the total data LPSTR lpBuffer; // Buffer for storing read data } REQUEST_CONTEXT;Dadurch kann man jedem Request die Möglichkeit geben, Daten abzulegen und bekommt diese dann in jedem Aufruf der Callback-Funktion automatisch zur Verfügung gestellt. Da die Anzahl der Requests ja variabel ist, habe ich die einzelnen Instanzen der obigen Struktur in einem std::vector ablegen wollen:
// Holds instances of the context value structure std::vector<REQUEST_CONTEXT> rcContexts;Doch genau hier lag der Fehler, da ich innerhalb einer Schleife immer die einzelnen Anfragen über push_back() eingefügt und dann zur weiteren Verarbeitung einen Zeiger auf das letzte Element des vectors verwendet habe. Dumm nur, dass durch das push_back() im nächsten Durchlauf der alte Pointer nicht mehr gültig war, da ja durch die Größenänderung alles neu alloziert werden muss. Ich habe jetzt stattdessen eine Liste genommen und hier funktioniert dann auch alles wie erwartet

Andere Sache: Bist du dir wirklich sicher, dass das hier nichts mit Threads zu tun hat? Ich habe nämlich dieses Tutorial als Grundlage genommen und dort wird ziemlich viel über Threads gesagt und unter anderem auch eine CRITICAL_SECTION eingerichtet.