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 benediktibk

    PS: 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


Anmelden zum Antworten