Happyman0815 Geschrieben 25. März 2009 Geschrieben 25. März 2009 Hallo Leute! Ich bin auf der suche nach einer Funktion die mir den Seitenquelltext einer Homepage in einem String ablegt. Es Gibt die Funktion URLDownloadToFile(..); allerdings legt die mir den Quelltext in eine Datei ab. Meine Notlösung sieht derzeit so aus: //Laden des Quelltextes der Hompage "hp" in die Datei "DAT1" hr = URLDownloadToFile ( 0, hp, "DAT1", 0, 0 ); Sleep(100); //Öffnen der Datei "DAT1" um den Quelltext aus der Datei auslesen zu können ifstream fin("DAT1"); if (fin.is_open()) { //Speichern des Quelltextes in dem String "quellcode" fin.read(quellcode,1000); fin.close(); } else { cout << "Error opening file DAT1"; } Sleep(100); Da ich komplette Webseiten durchsuchen möchte laufen bei mir ca. 16 Threads in while(true) schleifen die diese operation ständig ausführen. Da ich mit so vielen Dateien arbeitet kommt es regelmäßig zu _CrtIsValidHeapPointer Fehlern. Ich muss dringend diese Notlösung loswerden um endlich nicht mehr mit Dateien hantieren zu müssen!!!! Ich hoffe einer von euch weiß einen Rat Gruß :new Happyman0815 :new Zitieren
Klotzkopp Geschrieben 25. März 2009 Geschrieben 25. März 2009 Da ich komplette Webseiten durchsuchen möchte laufen bei mir ca. 16 Threads in while(true) schleifen die diese operation ständig ausführen. Da ich mit so vielen Dateien arbeitet kommt es regelmäßig zu _CrtIsValidHeapPointer Fehlern.Das Problem würde vermutlich schon verschwinden, wenn du nicht in jedem Thread denselben Dateinamen (vielleicht sogar denselben Puffer?) benutzen würdest. Ich muss dringend diese Notlösung loswerden um endlich nicht mehr mit Dateien hantieren zu müssen!!!! URLOpenStream Function () Einfacher ist aber vermutlich cURL and libcurl Zitieren
Happyman0815 Geschrieben 25. März 2009 Autor Geschrieben 25. März 2009 Hallo nochmal, Das Problem würde vermutlich schon verschwinden, wenn du nicht in jedem Thread denselben Dateinamen (vielleicht sogar denselben Puffer?) benutzen würdest. Der Dateiname ist bei jedem Thread bereits unterschiedlich. (DAT1, .... ,DAT16) Ob diese nun den selben buffer verwenden weiß ich nicht. Könntest du mir ein kleines Sample geben zu folgender Funktion? URLOpenStream Function (...) Ich melde mich bis 20.00 Uhr ca. erstmal ab! Danke schonmal für die Tipps, in cURL muss ich micht später erstmal einarbeiten. Gruß Happyman0815 Zitieren
Happyman0815 Geschrieben 28. März 2009 Autor Geschrieben 28. März 2009 Hallo Leute! Ich komme mit meinem Problem kaum weiter. Den Quellcode möchte ich gerne so gestallten, dass man keine externen Programme benötigt, sondern alles auch auf anderen Windows Rechnern läuft. Ich grübel jetzt schon seit einigen Stunden über die URLOpenStream Function () nach aber komm irgendwie zu keiner Lösung Wenn einer etwas mehr wissen hat über Sockets, etc. als ich wäre es nett mir ein kleines Sample für mein Problem zu geben. :old Gruß Happyman0815 Zitieren
Happyman0815 Geschrieben 29. März 2009 Autor Geschrieben 29. März 2009 Ich habe jetzt immer noch die Lösung mit den Dateien aber zumindest habe ich keine Abstürze mehr. Des Rätsels Lösung war: ifstream fin; fin.open(dat, ios::in); // <-- bei paralleler Ausführung in Threads gibt es Fehler Wenn eine Datei in einem anderen Thread parallel geöffnet wird, gibt es den Pointer Fehler! Ich setze dafür jetzt ein Semapohren System ein: while(!sema_file_open); sema_file_open=false; fin.open(dat, ios::in); sema_file_open=true; Damit funktioniert zumindest erstmal die Notlösung. Gruß Happyman0815 Zitieren
Klotzkopp Geschrieben 30. März 2009 Geschrieben 30. März 2009 Wenn eine Datei in einem anderen Thread parallel geöffnet wird, gibt es den Pointer Fehler! Das kann eigentlich nicht passieren, wenn die Dateinamen wirklich unterschiedlich sind. Wie hast du das denn sichergestellt? Ich setze dafür jetzt ein Semapohren System ein: while(!sema_file_open); sema_file_open=false; fin.open(dat, ios::in); sema_file_open=true; [/CODE] Damit funktioniert zumindest erstmal die Notlösung.Wenn das funktioniert, ist es Zufall. Man kann Threads nicht mit einfachen Variablen synchronisieren (auch dann nicht, wenn sema_file_open als [i]volatile[/i] deklariert ist). Benutz die Synchonisationsprimitiven deiner Threadbibliothek. Überhaupt ist Aktives Warten bei Multitasking oder Multithreading eine sehr schlechte Idee. Zitieren
Happyman0815 Geschrieben 30. März 2009 Autor Geschrieben 30. März 2009 Hallo! Das kann eigentlich nicht passieren, wenn die Dateinamen wirklich unterschiedlich sind. Wie hast du das denn sichergestellt? es gibt eine globale Variable die hochgezählt wird: char dat[20] = {"C:/Temp/xx/DATxx@"}; for(i=0; dat[i] != '@'; i++); dat[i] = '\0'; if((char) verzeichnis_temp[0]!= 'z' && (char) verzeichnis_temp[1]!= 'z') { for(i=0; dat[i] != 'x'; i++); dat[i] = (char) verzeichnis_temp[0]; dat[i+1] = (char) verzeichnis_temp[1]; } for(i=0; dat[i] != 'x'; i++); //Hier bekommt jeder Thread eine eigene Datei: dat[i] = (char) (thread_counter/10) +48; dat[i+1] = (char) (thread_counter%10) +48; Ist derzeit noch "etwas" durcheinander. Der Thread Counter wird mit jedem erstellten Thread einen höher gezählt und die max. zweistellige Zahl dann in Char umgewandelt. Diese Werden dann dem Pfad hinzugefügt. Hab das so gemacht da man mit einem Menü Thread, dynamisch Threads hinzufügen und wieder entfernen kann. Klappt soweit ganz gut habs auch bis 100 Threads mal getestet. Wenn das funktioniert, ist es Zufall. Man kann Threads nicht mit einfachen Variablen synchronisieren (auch dann nicht, wenn sema_file_open als volatile deklariert ist). Benutz die Synchonisationsprimitiven deiner Threadbibliothek. Überhaupt ist Aktives Warten bei Multitasking oder Multithreading eine sehr schlechte Idee. Uff ja ich hab mir schon gedacht das das zufall ist. Das Programm schmiert auch alle paar Stunden mal wieder ab. Die Wahrscheinlichkeit eines Absturz ist aber geringer geworden :bimei Hast du ein kleines Sample wie das vernünftig mit der Synchronisation klappt? (Ich brauch dringend die "URL to String" Lösung :old ) Gruß Happyman0815 Zitieren
Klotzkopp Geschrieben 31. März 2009 Geschrieben 31. März 2009 es gibt eine globale Variable die hochgezählt wird: Ist derzeit noch "etwas" durcheinander. Der Thread Counter wird mit jedem erstellten Thread einen höher gezählt und die max. zweistellige Zahl dann in Char umgewandelt. Diese Werden dann dem Pfad hinzugefügt.Auch das ist nicht sicher. Du hast nicht gezeigt, wo die Variable hochgezählt wird, aber stell dir mal vor, zwischen dem Hochzählen und dem Zusammenbasteln des Dateinamens zählt ein anderer Thread die Variable nochmal hoch. Oder zwischen den Zuweisungen von dat und dat[i+1]. Das alles kann passieren. Globale Variablen sind nicht threadsicher. Das Programm schmiert auch alle paar Stunden mal wieder ab. Die Wahrscheinlichkeit eines Absturz ist aber geringer geworden :bimeiDas ist kein gutes Zeichen. Du kannst durch Rumbasteln die Wahrscheinlichkeit, dass so ein Synchronisierungsproblem auftritt, einschränken, aber du kannst es nie völlig ausschließen. Im besten Fall sorgst du nur dafür, dass sich der Fehler schlechter reproduzieren und damit kaum mehr aufspüren lässt. Es kann auch sein, dass deine Basteleien bewirken, dass das Programm auf deinem Rechner stabiler läuft, auf anderen dafür umso schneller abstürzt. Allein die Sleep-Aufrufe in deinem ersten Beitrag sind schon höchst verdächtig. Lass mich raten, damit läuft es besser? Hast du ein kleines Sample wie das vernünftig mit der Synchronisation klappt?Threads sind kein einfaches Thema, weil Threadsynchronisierung kein einfaches Thema ist. Da du die WinAPI verwendest, wäre der erste Schritt, dass du dich in die Synchronisierungsobjekte der WinAPI-Threads einarbeitest: Events, Critical Sections, Mutexe, Semaphoren, Condition Variables (ab Vista/Server 2008). Für dich sind vermutlich zunächst Critical Sections und die Interlocked...-Funktionen interessant: Using Critical Section Objects (Windows) InterlockedIncrement Function (Windows) Zitieren
Happyman0815 Geschrieben 31. März 2009 Autor Geschrieben 31. März 2009 Hallo! Die Zuweisungen für den Dateinamen sind in dem Sinne sicher, dass Threads nur im 500 ms Takt erstellt und deletet werden können. Das sollte (auch wenn es schlecht programmiert ist) funktionieren. (und das Sleep konnte ich dank meinen pseudo Semaphoren jetzt auch raus nehmen ) Bei all den anderen Faktoren hast du wohl recht und ich muss mal schauen wie ich das mit einer vernünftigen Synchronisierung in den Griff bekomme. Es gibt denk ich mal auch Threads für C++ (nicht WinAPI)? Vielleicht sollte ich mich da mal einarbeiten damit ich später nicht von Windows abhängig bin. Danke schonmal für die Hilfe! Ich bin in sachen Threads (ist meine erste Threadprogrammierung) auf jedenfall schonmal um einiges weiter gekommen! Gruß Happyman0815 Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.