rs232



  • Synchronisationsprobleme würd ich spontan sagen... wartet die Applikation auf irgendwas das der Thread auslöst?

    -junix



  • hier mal der code aus dem tutorial:

    header form:

    //---------------------------------------------------------------------------
    
    #ifndef Unit1H
    #define Unit1H
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    #include <ExtCtrls.hpp>
    //---------------------------------------------------------------------------
    class TForm1 : public TForm
    {
    __published:	// Von der IDE verwaltete Komponenten
        TPanel *Panel1;
        TMemo *Memo1;
        TMemo *Memo2;
        TEdit *Edit1;
        TButton *Button1;
        void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
        void __fastcall FormCreate(TObject *Sender);
        void __fastcall Memo1KeyPress(TObject *Sender, char &Key);
    private:	// Anwender-Deklarationen
    public:		// Anwender-Deklarationen
        __fastcall TForm1(TComponent* Owner);
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm1 *Form1;
    //---------------------------------------------------------------------------
    #endif
    

    cpp form

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    #include "Unit2.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    
    HANDLE hComm = NULL;
    TRead *ReadThread;
    COMMTIMEOUTS ctmoNew = {0}, ctmoOld;
    
    #pragma resource "*.dfm"
    TForm1 *Form1;
    
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
    {
        // BEENDE DEN THREAD.
        ReadThread->Terminate();
    
        // WARTEN BIS DER THREAD BEENDET IST,
        // LEERE DEN INTERNEN COMM BUFFER,
        // STELLE DIE VORHERIGEN TIMEOUT SETTINGS WIEDER HER,
        // UND SCHLIESSE DEN COMPORT.
        Sleep(500);
        PurgeComm(hComm, PURGE_RXABORT);
        SetCommTimeouts(hComm, &ctmoOld);
        CloseHandle(hComm);
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::FormCreate(TObject *Sender)
    {
        DCB dcbCommPort;
    
        // COMM PORT ÖFFNEN.
        // ERSETZEN SIE "COM2" MIT EINEM STRING ODER "COM1", "COM3", ETC. UM EINEN
        // ANDEREN PORT ZU ÖFFNEN.
        hComm = CreateFile ("COM1",GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
    
        // WENN DER PORT NICHT GEÖFFNET WERDEN KANN, ANWENDUNG BEENDEN
        if(hComm == INVALID_HANDLE_VALUE)
        {
        Application->MessageBoxA("Fehler","Fehler",mbOK);
        Application->Terminate();
        }
    
        // COMM TIMEOUTS FÜR UNSER BEISPIEL SETZEN.
        GetCommTimeouts(hComm,&ctmoOld);
        ctmoNew.ReadTotalTimeoutConstant = 10;
        ctmoNew.ReadTotalTimeoutMultiplier = 0;
        ctmoNew.WriteTotalTimeoutMultiplier = 0;
        ctmoNew.WriteTotalTimeoutConstant = 0;
        SetCommTimeouts(hComm, &ctmoNew);
    
        // BAUDRATE, PARITÄT, WORTLÄNMGE, UND STOPBITS SETZEN.
        // ES GIBT AUCH ANDERE WEGE DIESE ZU SETZEN ABER DIES IST DER EINFACHSTE.
        // WENN SIE SPÄTER ANDEREN CODE FÜR DIE BAUSRATE USW. HINZUFÜGEN WOLLEN, DENKEN
        // SIE DARAN, DASS DAS ARGUMENT FÜR BuildCommDCB EINEN POINTER AUF EIN
        // STRING SEIN MUSS.
        // DENKEN SIE AUCH DARAN, DASS DIE BuildCommDCB()-DEFAULTS NICHT FÜR HANDSHAKING
        // GESETZT SIND.
        dcbCommPort.DCBlength = sizeof(DCB);
        GetCommState(hComm, &dcbCommPort);
        BuildCommDCB("9600,N,8,1", &dcbCommPort);
        SetCommState(hComm, &dcbCommPort);
    
        // AKRIVIERE DEN THREAD
        ReadThread = new TRead(false);
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::Memo1KeyPress(TObject *Sender, char &Key)
    {
        // SENDE JEDE MEMO-EINGABE
        TransmitCommChar(hComm, Key);
    
        // DIES VERHINDERT DASS ANZEIGEN VON UNGÜLTIGEN ZEICHEN.
        // WENN SIE MIT EINEM GERÄT VERBUNDEN SIND WELCHES CHARACTER ZURÜCKSENDET,
        // SETZEN SIE EINFACH Key = 0.
        if(Key != 13 && (Key < ' ' || Key > 'z')) Key = 0;
    
    }
    //---------------------------------------------------------------------------
    

    header thread

    //---------------------------------------------------------------------------
    
    #ifndef Unit2H
    #define Unit2H
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    //---------------------------------------------------------------------------
    class TRead : public TThread
    {
    private:
    protected:
        void __fastcall DisplayIt(void); // FÜGEN SIE DIESE ZEILE HINZU
        void __fastcall Execute();
    public:
        __fastcall TRead(bool CreateSuspended);
    };
    //---------------------------------------------------------------------------
    #endif
    

    cpp thread

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    #include "Unit2.h"
    #pragma package(smart_init)
    
    extern HANDLE hComm;
    char InBuff[100];
    
    //---------------------------------------------------------------------------
    
    //   Wichtig: Methoden und Eigenschaften von Objekten der VCL können nur in
    //   in Methoden verwendet werden, die Synchronize aufrufen, z.B.:
    //
    //      Synchronize(UpdateCaption);
    //
    //   wobei UpdateCaption so aussehen könnte:
    //
    //      void __fastcall Unit2::UpdateCaption()
    //      {
    //        Form1->Caption = "In Thread aktualisiert";
    //      }
    //---------------------------------------------------------------------------
    
    __fastcall TRead::TRead(bool CreateSuspended)
        : TThread(CreateSuspended)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TRead::DisplayIt()
    {
        // ZEIGE DEN EMPFANGENEN TEXT AN.
        Form1->Memo1->SetSelTextBuf(InBuff);
    }
    //---------------------------------------------------------------------------
    void __fastcall TRead::Execute()
    {
        //---- Place thread code here ----
    
        DWORD dwBytesRead;
    
        // DAS THREAD-OBJECT SOLL AUTOMATISCH ZERSTÖRT WERDEN WENN DER THREAD
        // BEENDET WIRD.
        FreeOnTerminate = true;
    
        while(1)
        {
            // VERSUCHE DATEN VOM COM-PORT ZU LESEN
            // WENN KEINE DATEN DA SIND, WIRD EIN TIMOUT AUFTRETEN UND EIN ERNEUTER VERSUCH
            // GESTARTET. WENN DATEN DA SIND, WERDEN DIESE ANGEZEIGT.
            ReadFile(hComm, InBuff, 50, &dwBytesRead, NULL);
            if(dwBytesRead)
            {
                InBuff[dwBytesRead] = 0; // NULL-TERMINATE DEN STRING
                Synchronize(DisplayIt);
            }
        }
    }
    //---------------------------------------------------------------------------
    

    wenn ich die applikation starte, erscheinen zwei memo felder nebeneinander. alles was in den rechten reinkommt, das ist ausgang, und in dem linken ist eingang. es funktioniert, wenn ich die daten langsam schreibe, also wenn ich einen ascii sende. nur wenn ich mehrere ascii schnell hintereinander sende, dann hängt sie wohl.

    kannste ja ausprobieren.

    ich kenne mich mit beiden: rs232 und TThread zuwenig aus, um eine lösung zu erfahren. würde mich freuen, wenn du mir weiterhelfen kannst!

    gruß gerd



  • Voilà der Synchronize Aufruf ist es... Damit beschäftigst du das Formular zu stark und es kann die Messages nichtmehr abarbeiten... Deshalb sollte man Threads möglichst vom GUI über ne MessageBox wie z.B. die Windows Messages entkoppeln...

    -junix



  • hallo,

    könnte es sein, dass ich das problem vielleicht selber gelöst habe?

    wie gesagt, ich kenne mich nicht mit threads aus!

    ich habe folgendes unternommen, und es "scheint" zu funktionieren:

    ich fügte der threadklasse eine weitere funktion zu (ist vielleicht etwas umfangreicher,ok) und benannte sie DisplayIt2. diese funktion tut allerdings nichts!

    den code unten in der klasse änderte ich wie folgt ab:

    while(1)
        {
            // VERSUCHE DATEN VOM COM-PORT ZU LESEN
            // WENN KEINE DATEN DA SIND, WIRD EIN TIMOUT AUFTRETEN UND EIN ERNEUTER VERSUCH
            // GESTARTET. WENN DATEN DA SIND, WERDEN DIESE ANGEZEIGT.
            ReadFile(hComm, InBuff, 50, &dwBytesRead, NULL);
            if(dwBytesRead)
            {
                InBuff[dwBytesRead] = 0; // NULL-TERMINATE DEN STRING
                Synchronize(DisplayIt);
            }
            else
            {
            Synchronize(DisplayIt2);
            }
        }
    

    sollte dies der fehler sein, der jetzt gelöst ist, sage ich trotzdem danke, weil du mich mit dem synchronisieren drauf gebracht hattest. in der hilfe steht unter threads, das ständig "Synchronize()" ausgeführt werden muss, damit ein thread weiterarbeitet.

    gruß gerd



  • Erscheint mir jetzt etwas unlogisch irgendwie....

    -junix



  • in der hilfe steht für Synchronize:

    Beschreibung

    Synchronize löst den Aufruf einer bestimmten Methode aus, die vom VCL-Haupt-Thread ausgeführt werden soll. Durch dieses indirekte Verfahren werden Konflikte in Multithread-Anwendungen vermieden. Wenn Sie nicht sicher sind, ob ein Methodenaufruf Thread-sicher ist, rufen Sie die Methode vom VCL-Haupt-Thread aus auf, indem Sie sie an die Methode Synchronize übergeben.

    Der Thread wird unterbrochen, während die angegebene Methode ausgeführt wird.

    Hinweis

    Unsichere Methoden können Sie auch durch kritische Sektionen oder mit Hilfe eines Synchronisierers, der mehrfaches Lesen, aber nur exklusives Schreiben zuläßt, schützen.

    ps:es scheint ja zu funktionieren, oder bist du da anderer meinung?

    gruß gerd



  • Was mir nicht klar ist: Wozu die leere funktion? Wieso funktionierts dann plötzlich?

    -junix



  • weil er wahrscheinlich einfach nur synchronize aufrufen muss. ich stelle mir es so vor:

    1. Synchronize-aufruf der funktion aus dem thread
    2. in der funktion Synchronize werden intern irgendwelche sachen zur beruhigung der vcl übergeben, sodass sich alles wieder synchronisiert
    3. aufruf der übergebenden funktion

    anders könnte ich es mir nicht erklären, was meinst du?

    gruß gerd



  • Etwas vage würde ich sagen... Hab leider keine VCL Sourcen da sonst würde ich mir das mal reinziehen... Mir behagt das jedenfalls nicht, wenn ich nicht weiss wieso etwas plötzlich funktioniert... vor Allem wenn der Grund wiesos plötzlich Funktioniert nicht nachvollziehbar ist....

    -junix



  • vielleicht kann es jemand anders bei interesse etwas nachvollziehen! 🙂

    danke trotzdem erstmal!

    gruß gerd


Anmelden zum Antworten