Ungültiges Handle bei TThread::WaitFor()/ in WindowProc
-
Der Titel sagt es aus, ich bin mir nicht ganz sicher, wo der Fehler liegt. Nach der Fehlermeldung springt der BCB zwar in Zeile 4 von folgendem Code:
//Botschaften abfangen void __fastcall TForm1::NewWindowProc(TMessage &Message) { if (Message.Msg==CM_THREADBEENDET) ThreadBeendet(Message); else OldWindowProc(Message); }
Jedoch komme ich bis in die Zeile 44, zum WaitFor, von folgendem, wenn ich debugge:
void __fastcall TForm1::ThreadBeendet(TMessage Message) { short start[3]; AnsiString tupel_ausg, temp_string; int naechstes_tupel=-1; int thread_aktuell; //Ausständiges Tupel suchen for (int i=0; i<tupel_anzahl && naechstes_tupel==-1; i++) { naechstes_tupel=i; for (int j=0; j<thread_anzahl_max; j++) { if (thread_besetzt[j]==naechstes_tupel) naechstes_tupel=-1; } } //Ergebnis ausgeben tupel_ausg=""; for (int i=3; i>=0; i--) { tupel_ausg+=IntToStr(tupel[Message.WParam]->get_glied(i))+"-"; } tupel_ausg.SetLength(tupel_ausg.Length()-1); tupel_ausg+=": " + IntToStr(Message.LParam); if (!CheckBox9->Checked || Message.Result==0) Memo1->Lines->Add(tupel_ausg); tupel_berechnet[Message.WParam]=true; Application->ProcessMessages(); //Falls noch ein Tupel übrig, dieses berechnen if (naechstes_tupel!=-1 && !abbrechen) { thread_aktuell=-1; //Leeren Thread suchen for (int i=0; i<thread_anzahl_max; i++) { if (Message.WParam==thread_besetzt[i]) thread_aktuell=i; } //start zusammenbasteln start[0]=tupel[naechstes_tupel]->get_glied(1); start[1]=tupel[naechstes_tupel]->get_glied(2); start[2]=tupel[naechstes_tupel]->get_glied(3); if (threads[thread_aktuell]!=NULL) { threads[thread_aktuell]->Resume(); threads[thread_aktuell]->WaitFor(); delete threads[thread_aktuell]; } threads[thread_aktuell]=new CTupelBaum (start,tupel[naechstes_tupel]->get_glied(0),naechstes_tupel,Form1); thread_besetzt[thread_aktuell]=naechstes_tupel; } //Falls kein ausständiges Tupel, Berechnung beenden else { //Berechnungsdauer ausgeben zeit_ende=Time(); Label7->Caption=(zeit_ende-zeit_start); abbrechen=false; for (int i=0; i<thread_anzahl_max; i++) delete threads[i]; for (int i=0; i<tupel_anzahl; i++) delete tupel[i]; delete[] *threads; delete[] *tupel; delete[] thread_besetzt; delete[] tupel_berechnet; momentane_berechnung=false; } }
Gesendet wird die Botschaft hier:
// //Execute //Aufgabe: Den Tupelbaum berechnen void __fastcall CTupelBaum::Execute() { if (start_tupel.NaechstesTupelUnten_pruefen()) ergebnis=TupelAst(start_tupel, true); else ergebnis=start_tupel.Produkt(); //Botschaft versenden, dass die Berechnung beendet ist PostMessage(Hauptthread->Handle,CM_THREADBEENDET,tupel_id,ergebnis); Suspend(); }
Die Fehlermeldung lautet:
Systemfehler. Code: 6. Das Handle ist ungültig.
Das Problem tritt nur beim letzten Thread der ersten Generation auf, der beendet wird. Gestartet wird der Ablauf durch:
//Erste Tupel berechnen lassen l=0; for (int i=0; i<thread_anzahl_max && i<tupel_anzahl; i++) { start[0]=tupel[l]->get_glied(1); start[1]=tupel[l]->get_glied(2); start[2]=tupel[l]->get_glied(3); if (threads[i]!=NULL) delete threads[i]; threads[i]=new CTupelBaum(start,tupel[l]->get_glied(0),l,Form1); thread_besetzt[i]=l; l++; }
Das Resume() und Suspend waren nur ein Versuch, das Problem zu umgehen.
Ich bin dankbar über jeden Denkanstoss,
MfG benediktibkPS: Bei dem Projekt brauche ich irgendwie viel Hilfe...
Edit: Mir ist aufgefallen, dass schließlich mehrere Instanzen von ThreadBeendet vorhanden sein könnten, weshalb ich eine CricitcalSection drum herum gebaut habe:
//Botschaften abfangen void __fastcall TForm1::NewWindowProc(TMessage &Message) { if (Message.Msg==CM_THREADBEENDET) { Thread_beendet->Acquire(); ThreadBeendet(Message); Thread_beendet->Leave(); } else OldWindowProc(Message); }
Nun springt der BCB in die Leave-Zeile, jedoch komme ich beim Debuggen nur bis zur WaitFor-Methode (siehe oben), weshalb ich vermute, dass der Fehler beim WaitFor liegt.
-
Du versuchst auf einen Thread zuzugreifen, der bereits gelöscht wurde. Klassischer Logikfehler...
-
Ich kam, sah und siegte über den Logikfehler, dass ich Threads löschen muss. Jetzt gewöhnt man sich einmal daran, immer schön brav alles zu löschen, was man reserviert, und dann scheitert man an dieser Gewohnheit...
Naja, solange es noch Joe gibt :p
Danke, benediktibk