TThread einbinden - Fehler E2268 Aufruf der undefinierten Funktion



  • Hallo,

    habe seit Stunden ein Problem und verzweifel bald:

    Mit Neu lege ich zwei neue Thread-Objekte an; eines nenne
    ich ThreadClients und das andere ThreadSenden.

    Das erste klappt wunderbar; beim zweiten kommt immer der E2268 Fehler.
    **Main_NH3.cpp(4115): Analyse von: void _fastcall TForm1::frm1_tmrStartTimer(TObject 😉
    [C++ Fehler] Main_NH3.cpp(4275): E2268 Aufruf der undefinierten Funktion 'ThreadSenden'
    Vollständiger Parser-Kontext
    Main_NH3.cpp(4269): Analyse von: void _fastcall TForm1::frm1_tmrThreadATimer(TObject 😉
    **
    Auch aus dem Projekt entfernen und neu einbinden bringt kein Erfolg!?

    Die Threads starte ich jeweils separat in einem Timer.

    // TIMER T
    void __fastcall TForm1::frm1_tmrThreadCTimer(TObject *Sender)
    {try {                                                                          // Fehlerroutine Start
    
     Form1->frm1_tmrThreadC->Enabled=false;                                         // und Timer stoppen
                                                                                    // CLIENTEN ZÄHLEN
     ThreadClients(false);                                                          // Thread starten (noch nicht starten=true)
                                                                                    // AUSGANG
     } catch(Exception& e) { MessageBox(NULL, e.Message.c_str(), "TForm1::frm1_tmrThreadCTimer()", MB_OK); }  // Fehler anzeigen
    }
    void __fastcall TForm1::frm1_tmrThreadATimer(TObject *Sender)
    {try {                                                                          // Fehlerroutine Start
    
     Form1->frm1_tmrThreadA->Enabled=false;                                         // und Timer stoppen
                                                                                    // BENACHRICHTIGEN ABSETZEN
     ThreadSenden(false);                                                           // Thread starten (noch nicht starten=true)
    
     } catch(Exception& e) { MessageBox(NULL, e.Message.c_str(), "TForm1::frm1_tmrThreadATimer()", MB_OK); }  // Fehler anzeigen
    }
    

    Habe alles mögliche probiert und komme nicht mehr weiter...

    Hier mal der Code von ThreadSenden.cpp:

    //---------------------------------------------------------------------------
    
    #include <inifiles.hpp>                                                         // INI Files
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Main_NH3.h"                                                           // Form1
    #include "Thread_Senden.h"                                                      // Thread 2
    #pragma package(smart_init)
    
    //---------------------------------------------------------------------------
    
    __fastcall ThreadSenden::ThreadSenden(bool CreateSuspended) : TThread(CreateSuspended)
    {
     switch(Form1->iThPrioA) {                                                      // Thread wie ausführen...
     case 0:  Priority=tpIdle;         break;                                       // Prio nur wenn System im Leerlauf ist
     case 1:  Priority=tpLowest;       break;                                       // Prio 2 Stufen unter Normal
     case 2:  Priority=tpLower;        break;                                       // Prio 1 Stufe  unter Normal
     case 3:  Priority=tpNormal;       break;                                       // Prio ist Normal
     case 4:  Priority=tpHigher;       break;                                       // Prio 1 Stufe  über Normal
     case 5:  Priority=tpHighest;      break;                                       // Prio 2 Stufen über Normal
     case 6:  Priority=tpTimeCritical; break;                                       // Prio Höchste
     default: Priority=tpIdle;         break;                                       // Prio nur wenn System im Leerlauf ist
     }                                                                              // endswitch(iPrio
    
     //FatalException=TObject...;                                                     // bei Fehler autom. freigeben
     //OnTerminate=ThreadDelete;                                                      // und freigeben starten
     FreeOnTerminate=true;                                                          // nach Beendigung autom. freigeben
    }
    
    //---------------------------------------------------------------------------
    //--- THREADS ---
    //---------------------------------------------------------------------------
    void __fastcall ThreadSenden::Execute()
    {try {                                                                          // Fehlerroutine Start
    
     while (!ThreadSenden::Terminated) {                                            // abarbeiten bis Abbruchbefehl kommt
    
      Synchronize(Versenden);                                                       // und synchronisiert   los
      //Versenden();                                                                // nicht synchronisiert los
    
      if(ThreadSenden::Terminated==true) { break; }                                 // Abbruch raus
    
      break;                                                                        // und fertig
     }                                                                              // ende while()
    
     //-----------------------------------------------------------------------------// THREAD ENDE
     Form1->frm1_tmrThreadA->Enabled=Terminated==false;                             // und Timer wieder starten (falls nicht Abbruch)
    
     } catch(Exception& e) { MessageBox(NULL, e.Message.c_str(), "TThreadSenden::Execute()", MB_OK); }  // Fehler anzeigen
    }
    
    //---------------------------------------------------------------------------
    //--- FUNKTIONEN IM THREAD ---
    //---------------------------------------------------------------------------
    
    // FUNKTION D
    AnsiString DatenPipe(int p1, int p2, AnsiString pt1, AnsiString pt2)
    {try {                                                                          // Fehlerroutine Start
     Integer i2,i3; AnsiString z1,z2;                                               // Vars definieren
    
     if(pt1.Length()==0) { pt1="||"; }                                              // Stringvorgabe korrigieren
     z1=pt1;                                                                        // und übergeben
    
     switch(p1) {                                                                   // was machen?
     case 1:                                                                        // AUSLESEN STRING
     case 3:                                                                        // AUSLESEN INTEGER
      for(int i1=1;i1<=p2;i1++) {                                                   // x. Pipe suchen
       i2=z1.AnsiPos("|");                                                          // Pipe suchen
       if(i2==0) { z1=z1+"|"; i2=z1.AnsiPos("|"); }                                 // keines gefunden, neues Pipe anhängen
       z1=z1.SubString(i2+1,9999);                                                  // String ab Pipe+1 abschneiden
      }                                                                             // ende for(int i2)
    
      i2=z1.AnsiPos("|");                                                           // noch nächstes Pipe suchen
      z1=z1.SubString( 1,i2-1);                                                     // und bis nächstes Pipe den Inhalt ausschneiden
      if(pt2=="!!") { z1=z1.Trim(); }                                               // ohne Leerstellen zurückgeben
    
      if(p1==3 && z1.Length()==0) { z1="0"; }                                       // Rückgabe für Integer (leerer String gibt Fehlermeldung!)
      return z1;                                                                    // und Inhalt zurückgeben
     case 2:                                                                        // SCHREIBEN
     case 4:                                                                        // SCHREIBEN MIT FEHLERHINWEIS
      z2="";                                                                        // String vorbereitend löschen
      for(int i1=1;i1<=p2;i1++) {                                                   // x. Pipe suchen
       i2=z1.AnsiPos("|"); if(i2==0) { z1="|"; i2=1; }                              // Pipe suchen und ggfs. anhängen
       z2=z2+z1.SubString(1, i2);                                                   // und Rest merken
       z1=z1.SubString(i2+1,9999);                                                  // String ab Pipe+1 abschneiden
      }                                                                             // ende for(int i2)
    
      i2=z1.AnsiPos("|");                                                           // noch nächstes Pipe suchen
      z1=z2+pt2+z1.SubString(i2, pt1.Length());                                     // und pt2 einsetzen und ab nächstem Pipe anhängen
      return z1;                                                                    // und Inhalt zurückgeben
     }                                                                              // ende switch(p1
    
     return "";                                                                     // Standardrückgabe
    
     } catch(Exception& e) { MessageBox(NULL, e.Message.c_str(), "TThreadSenden::DatenPipe()", MB_OK); return ""; }  // Fehler anzeigen
    }
    
    // FUNKTION V
    void __fastcall ThreadSenden::Versenden()                                         // MESSAGE-FUNKTIONEN
    {Form1->frm1_btn8_AktuellClick(0);                                              // und los
    }
    
    // FUNKTION Z
    AnsiString ZeitStempel(int p1,AnsiString pt1)
    {try {                                                                          // Fehlerroutine Start
     AnsiString z1;                                                                 // Vars definieren
     TDateTime DateTime=Now();                                                      // Datum und Uhrzeit speichern
    
     switch(p1) {                                                                   // was zurückgeben
     case 0:                                                                        // KOMPLETTE ZEIT
     case 1: z1=FormatDateTime("dd.mm.yyyy, hh:nn:ss"    ,DateTime); break;         // KOMPLETTE ZEIT
     case 2: z1=FormatDateTime("dd.mm.yyyy"              ,DateTime); break;         // NUR DATUM;
     case 3: z1=FormatDateTime("hh:nn:ss"                ,DateTime); break;         // NUR UHRZEIT;
     case 4: z1=FormatDateTime("dd.mm.yyyy, hh:nn"       ,DateTime); break;         // KURZFORM
     case 5: z1=FormatDateTime("yyyy-mm-dd"              ,DateTime); break;         // NUR DATUM FÜR DATEI;
     case 6: z1=FormatDateTime("dd.mm.yyyy hh:nn:ss"     ,DateTime); break;         // KOMPLETTE ZEIT OHNE KOMMA
     case 7: z1=FormatDateTime("yyyy-mm-dd hh-nn-ss"     ,DateTime); break;         // LOGBUCHSTEMPEL;
     case 8: z1=FormatDateTime("yyyy-mm"                 ,DateTime); break;         // NUR DATUM FÜR DATEI;
     case 9: z1=FormatDateTime("yyyy-mm-dd hh-nn-ss-zzz" ,DateTime); break;         // LOGBUCHSTEMPEL MIT MILLISEKUNDEN;
     }                                                                              // ende p1
    
     return z1+"  ";                                                                // und Rückgabe der Zeit
    
     } catch(Exception& e) { MessageBox(NULL, e.Message.c_str(), "TThreadSenden::ZeitStempel()", MB_OK); return ""; }  // Fehler anzeigen
    }
    

    und der zugehörige Header:

    //---------------------------------------------------------------------------
    
    #ifndef Thread_SendenH
    #define Thread_SendenH
    
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    
     AnsiString DatenPipe(int p1, int p2, AnsiString pt1, AnsiString pt2);          // Funktion definieren
     AnsiString ZeitStempel(int p1, AnsiString pt1);                                // Funktion definieren
    
    //---------------------------------------------------------------------------
    
    class ThreadSenden : public TThread
    {
    private:
    protected:
            void __fastcall Execute();
            void __fastcall Versenden();                                            // Funktion deklarieren
    
    public:
            __fastcall ThreadSenden(bool CreateSuspended);
    };
    
    //---------------------------------------------------------------------------
    #endif
    

    Falls die Threads inhaltlich Fehler haben oder umständlich sind,
    dann bitte ich um Nachsehen. Das Thema Threads ist für mich ziemlich neu 😮

    Danke für jeden Tipp.

    Gruss Stefan Scholz



  • Hallo

    Der Fehler selber besagt das du wohl ein include auf die Unit mit ThreadSenden vergessen hast.
    Allerdings wird das nicht alle Probleme beheben, denn du hast ein Klasse ThreadSendern, keine Funktion. Du must erst eine Instanz der Klasse erstellen und dann kannst du für die Instanz eine Methode aufrufen.
    Bitte schau dir erstmal ein Tutorial über Threads an. Am besten auch eins über OOP.

    bis bald
    akari



  • Hallo Akari

    ich Esel hatte den Include in meiner Main.h vergessen und einfach
    nicht dran gedacht, weil ich dachte er würde es beim Einbinden als
    neues Object automatisch machen (der erste Thread war von früher
    noch included; daher lief der) 😞

    Danke für den Tip;
    Stefan


Anmelden zum Antworten