tutorials.de Buch-Aktion 05/2012
ERLEDIGT
NEIN
ANTWORTEN
11
ZUGRIFFE
4225
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Indian Indian ist offline Mitglied Gold
    Registriert seit
    May 2004
    Beiträge
    116
    Hi

    Wie und wo kann ich eine Bedingung in meiner Thread Funktion einbauen, so das der Thread SOFORT beendet wird und mit ihm auch alles aus dem Speicher verschwindet.


    kann einfach dieses Problem nicht lösen. Ich überwache meine ComPort über ein Thread. Jedoch schaffe ich es nicht diesen Thread zu beenden. Hab keine Ahnung wie ich denn Thread beenden kann und bis jetzt konnte mir auch keiner GENAU sagen wie. Es funktioniert einfach nicht. Es liegt an der WaitForMultipleObjects() bzw. WaitComEvent() Methode.

    Ziel ist es denn Thread für denn einen Dialog zu starten und wenn ein anderer Dialog gestarted wird denn ersten Thread zu beenden und wieder einen Thread für denn 2. Dialog zu starten.


    So starte ich denn Thread
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    BOOL CSerialPort::StartMonitoring()
    {
        if (!(m_Thread = AfxBeginThread(CommThread, this,THREAD_PRIORITY_NORMAL)))
            return FALSE;
        TRACE("Thread started\n");
        m_EndThread = FALSE;
     
        return TRUE;    
    }

    So versuche ich Ihn zu beenden (wird jedoch nur pausiert, bringt jedoch nichts)
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    
    BOOL CSerialPort::StopMonitoring()
    {
        m_EndThread = TRUE;
        m_Thread->SuspendThread();
        CloseHandle(m_hComm);
        TRACE("Thread suspended\n");
        return TRUE;    
    }

    Meine Thread Funktion
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    
    //
    //  The CommThread Function.
    //
    UINT CSerialPort::CommThread(LPVOID pParam)
    {
        // Cast the void pointer passed to the thread back to
        // a pointer of CSerialPort class
        CSerialPort *port = (CSerialPort*)pParam;
        
        // Set the status variable in the dialog class to
        // TRUE to indicate the thread is running.
        port->m_bThreadAlive = TRUE;    
            
        // Misc. variables
        DWORD BytesTransfered = 0; 
        DWORD Event = 0;
        DWORD CommEvent = 0;
        DWORD dwError = 0;
        COMSTAT comstat;
        BOOL  bResult = TRUE;
     
    //****Eingfügt aus Receiv Char Funktion weil comstat fehler Run Time Failure #3 Comstat gebracht hat****
        BOOL  bRead = TRUE; 
        DWORD BytesRead = 0;
        unsigned char RXBuff;
    //******************************************************************************************************
     
     
        // Clear comm buffers at startup
        if (port->m_hComm)      // check if the port is opened
            PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
     
     
        // begin forever loop.  This loop will run as long as the thread is alive.
        for (;;) 
        { 
            // Make a call to WaitCommEvent().  This call will return immediatly
            // because our port was created as an async port (FILE_FLAG_OVERLAPPED
            // and an m_OverlappedStructerlapped structure specified).  This call will cause the 
            // m_OverlappedStructerlapped element m_OverlappedStruct.hEvent, which is part of the m_hEventArray to 
            // be placed in a non-signeled state if there are no bytes available to be read,
            // or to a signeled state if there are bytes available.  If this event handle 
            // is set to the non-signeled state, it will be set to signeled when a 
            // character arrives at the port.
     
            // we do this for each port!
     
            bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);
     
            if (!bResult)  
            { 
                // If WaitCommEvent() returns FALSE, process the last error to determin
                // the reason..
                switch (dwError = GetLastError()) 
                { 
                case ERROR_IO_PENDING:  
                    { 
                        // This is a normal return value if there are no bytes
                        // to read at the port.
                        // Do nothing and continue
                        break;
                    }
                case 87:
                    {
                        // Under Windows NT, this value is returned for some reason.
                        // I have not investigated why, but it is also a valid reply
                        // Also do nothing and continue.
                        break;
                    }
                default:
                    {
                        // All other error codes indicate a serious error has
                        // occured.  Process this error.
                        port->ProcessErrorMessage("WaitCommEvent()");
                        break;
                    }
                }
            }
            else
            {
                // If WaitCommEvent() returns TRUE, check to be sure there are
                // actually bytes in the buffer to read.  
                //
                // If you are reading more than one byte at a time from the buffer 
                // (which this program does not do) you will have the situation occur 
                // where the first byte to arrive will cause the WaitForMultipleObjects() 
                // function to stop waiting.  The WaitForMultipleObjects() function 
                // resets the event handle in m_OverlappedStruct.hEvent to the non-signelead state
                // as it returns.  
                //
                // If in the time between the reset of this event and the call to 
                // ReadFile() more bytes arrive, the m_OverlappedStruct.hEvent handle will be set again
                // to the signeled state. When the call to ReadFile() occurs, it will 
                // read all of the bytes from the buffer, and the program will
                // loop back around to WaitCommEvent().
                // 
                // At this point you will be in the situation where m_OverlappedStruct.hEvent is set,
                // but there are no bytes available to read.  If you proceed and call
                // ReadFile(), it will return immediatly due to the async port setup, but
                // GetOverlappedResults() will not return until the next character arrives.
                //
                // It is not desirable for the GetOverlappedResults() function to be in 
                // this state.  The thread shutdown event (event 0) and the WriteFile()
                // event (Event2) will not work if the thread is blocked by GetOverlappedResults().
                //
                // The solution to this is to check the buffer with a call to ClearCommError().
                // This call will reset the event handle, and if there are no bytes to read
                // we can loop back through WaitCommEvent() again, then proceed.
                // If there are really bytes to read, do nothing and proceed.
            
                bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
     
                if (comstat.cbInQue == 0)
                    continue;
            }   // end if bResult
     
            // Main wait function.  This function will normally block the thread
            // until one of nine events occur that require action.
            Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);
     
            switch (Event)
            {
            case 0:
                {
                    // Shutdown event.  This is event zero so it will be
                    // the higest priority and be serviced first.
     
                    port->m_bThreadAlive = FALSE;
                    
                    // Kill this thread.  break is not needed, but makes me feel better.
                    AfxEndThread(100);
                    break;
                }
            case 1: // read event
                {
                    GetCommMask(port->m_hComm, &CommEvent);
                    if (CommEvent & EV_CTS)
                        ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_CTS_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
                    if (CommEvent & EV_RXFLAG)
                        ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RXFLAG_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
                    if (CommEvent & EV_BREAK)
                        ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_BREAK_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
                    if (CommEvent & EV_ERR)
                        ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_ERR_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
                    if (CommEvent & EV_RING)
                        ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RING_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
                    
                    if (CommEvent & EV_RXCHAR)
                        // Receive character event from port.
                        //ReceiveChar(port,comstat);   //Auskommentiert weil Fehlermeldung müsste funktionieren ka warum
     
    //****Eingfügt aus Receive Char Funktion weil comstat fehler Run Time Failure #3 Comstat gebracht hat****
        for (;;) 
        { 
            // Gain ownership of the comm port critical section.
            // This process guarantees no other part of this program 
            // is using the port object. 
            
            EnterCriticalSection(&port->m_csCommunicationSync);
     
            // ClearCommError() will update the COMSTAT structure and
            // clear any other errors.
            
            bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
     
            LeaveCriticalSection(&port->m_csCommunicationSync);
     
            // start forever loop.  I use this type of loop because I
            // do not know at runtime how many loops this will have to
            // run. My solution is to start a forever loop and to
            // break out of it when I have processed all of the
            // data available.  Be careful with this approach and
            // be sure your loop will exit.
            // My reasons for this are not as clear in this sample 
            // as it is in my production code, but I have found this 
            // solutiion to be the most efficient way to do this.
            
            if (comstat.cbInQue == 0)
            {
                // break out when all bytes have been read
                break;
            }
                            
            EnterCriticalSection(&port->m_csCommunicationSync);
     
            if (bRead)
            {
                bResult = ReadFile(port->m_hComm,       // Handle to COMM port 
                                   &RXBuff,             // RX Buffer Pointer
                                   1,                   // Read one byte
                                   &BytesRead,          // Stores number of bytes read
                                   &port->m_ov);        // pointer to the m_ov structure
                // deal with the error code 
                if (!bResult)  
                { 
                    switch (dwError = GetLastError()) 
                    { 
                        case ERROR_IO_PENDING:  
                            { 
                                // asynchronous i/o is still in progress 
                                // Proceed on to GetOverlappedResults();
                                bRead = FALSE;
                                break;
                            }
                        default:
                            {
                                // Another error has occured.  Process this error.
                                port->ProcessErrorMessage("ReadFile()");
                                break;
                            } 
                    }
                }
                else
                {
                    // ReadFile() returned complete. It is not necessary to call GetOverlappedResults()
                    bRead = TRUE;
                }
            }  // close if (bRead)
     
            if (!bRead)
            {
                bRead = TRUE;
                bResult = GetOverlappedResult(port->m_hComm,    // Handle to COMM port 
                                              &port->m_ov,      // Overlapped structure
                                              &BytesRead,       // Stores number of bytes read
                                              TRUE);            // Wait flag
     
                // deal with the error code 
                if (!bResult)  
                {
                    port->ProcessErrorMessage("GetOverlappedResults() in ReadFile()");
                }   
            }  // close if (!bRead)
                    
            LeaveCriticalSection(&port->m_csCommunicationSync);
     
            // notify parent that a byte was received
            ::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_RXCHAR, (WPARAM) RXBuff, (LPARAM) port->m_nPortNr);
        } // end forever loop
     
                        
                    break;
                }  
            case 2: // write event
                {
                    // Write character event from port
                    WriteChar(port);
                    break;
                }
     
            } // end switch
     
        } // close forever loop
    //******************************************************************************************************
        AfxEndThread(True);
        return 0;
    }



    HILFE
    Geändert von Indian (29.12.04 um 11:21 Uhr)
     

  2. #2
    Registriert seit
    Apr 2002
    Ort
    Delmenhorst (Niedersachsen)
    Beiträge
    3.567
    moin


    Du könntest deinen Thread bei jedem Durchlauf eine Adresse überprüfen lassen, die ihr in Form eines Pointers mitgegeben wurde.
    Dein "Hauptprogramm" kennt diese Adresse natürlich auch und kann dort einen bestimmten Wert ablegen.
    Da der Thread die Adresse bei jedem Durchlauf überprüft, kann er sich dann beenden wenn unter der Adresse ein der Wert zum beenden liegt.

    So kannst du natürlich auch andereFunktionen des Threads steuern...


    mfg
    umbrasaxum
     

  3. #3
    Avatar von Endurion
    Endurion Endurion ist offline Mitglied Diamant
    Registriert seit
    Apr 2004
    Beiträge
    2.151
    Deine WaitForMultipleObjects macht doch genau, was du willst. Da wird eine Reihe Events abgefragt. Setze selber eins dazu (mit CreateEvent erzeugt) und wenn du den Thread beenden willst, dann SetEvent dieses Event. Das WaitForMultipleObjects springt an der Stelle raus, du fragst ab, ob es dein Event war und lässt den Thread einfach aus der Endlosschleife rausspringen (ein Thread ist beendet, wenn seine Hauptroutine beendet wird). Fettich.
     

  4. #4
    Indian Indian ist offline Mitglied Gold
    Registriert seit
    May 2004
    Beiträge
    116
    Endurion:

    danke, ich hatte sowas auch vermutet. Jedoch weis ich nicht genau welches Event ich hier setzen muss.

    ich hab ein Handle m_hEventArray, welches 3 Felder enthält. Das m_hEventArray[0] enthält das shutdown event. Folgende Zeile warted natürlich auch ein event:

    Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);
    jetzt weiss ich leider nicht wie ich denn ersten Wert des Array hier beeinflussen kann so das diese nächste zeile ausgefürht werden kann. Eine variante könnte möglich sein, wenn ich HANDLE m_hShutdownEvent; als public deklariere und diese dann im Hauptprogramm einfach setze. Würde das funktionieren ?

    switch (Event)
    {
    case 0:
    {
    // Shutdown event. This is event zero so it will be
    // the higest priority and be serviced first.

    port->m_bThreadAlive = FALSE;

    // Kill this thread. break is not needed, but makes me feel better.
    AfxEndThread(100);
    break;
    }
    Kannst du mir hierbei helfen ?
    Geändert von Indian (30.12.04 um 09:41 Uhr)
     

  5. #5
    Avatar von Endurion
    Endurion Endurion ist offline Mitglied Diamant
    Registriert seit
    Apr 2004
    Beiträge
    2.151
    Genauso eigentlich, wenn das ShutDown-Event nur für die Stelle verwendet wird, reicht ein SetEvent mit dem Handle drin (ob public oder getter oder global ist egal), und dann sollte WaitForMultipleObjects da sofort rausspringen. Du musst natürlich bei der Abfrage sichergehen, dass es auch das ShutDown-Event ist, aber die Abfrage hast du ja schon drin. Ein einfaches return in der Threadroutine sollte reichen, so dass der Prozessor da rausspring und den Thread sauber beendet. Eventuell ein paar Sachen aufräumen, falls du das nicht schon woanders machst.

    Sollte so aussehen:

    SetEvent( port->m_hEventArray[0] );
     

  6. #6
    Indian Indian ist offline Mitglied Gold
    Registriert seit
    May 2004
    Beiträge
    116
    also ich habs versucht.

    Wenn ich das Event setze reagiert leider das Thread nicht. WaitForMultipleObjects reagiert einfach nicht darauf. Habe einen stop an der stelle gesetzt welcher nie aufgerufen wird.

    Ich bin momentan mit meinem Latein vollkommen am ende und ich weiss leider auch nicht mehr was ich fragen soll bzw. wo ich noch suchen soll. Mein Projekt ist nun fertig zu 99,9% ist aber nutzlos wenn ich diesen Thread welchen denn ComPort überwacht nicht beenden kann.

    Es muss doch irgendwie möglich diesen zu beenden ?
     

  7. #7
    Avatar von Endurion
    Endurion Endurion ist offline Mitglied Diamant
    Registriert seit
    Apr 2004
    Beiträge
    2.151
    Hängt der denn bei WaitForMultipleObjects oder schon bei WaitCommEvent?

    Wenn das gar nicht geht, kannst du da ein kleines Beispielprojekt nur mit den Threads machen und das hier reinstellen; dann gugg ich da mal rüber.
     

  8. #8
    Indian Indian ist offline Mitglied Gold
    Registriert seit
    May 2004
    Beiträge
    116
    danke für deine hilfe

    irgendwie funktioniert das wohl nicht so wie es funktionieren soll. Ob das nun an Visual Studio Net liegt oder am zeitlichen Abstand, kann ich leider jetzt nicht beurteilen. Ich denke denn Thread zu schliessen und wieder zu erzeugen im anderen Dialog, damit der ComPort überwacht werden kann, funktioniert wirklich nicht vom zeitlichen hergesehen. Ich meine die Freigabe bzw. belegen einer Windowsressources funktioniert einwandfrei wenn ich step by step im debug modus durch gehen. Ohne debug macht es bum oder es bleibt alles stehen.

    Naja wie auch immer. Ich habs nun anderst gemacht. Ich überwache denn ComPort und lasse denn Thread nur im Hauptdialog laufen und übergebe ganz einfach die eingelesen daten zu den anderen Dialogen. Natürlich setze ich vorher eine Variable auf true damit der Wert nicht im Hauptdialog bearbeitet werden soll sondern übergeben wird zu dem aufgerufenen Dialog.

    Mal ne frage hat Visual Studio Net ein paar macken ? Gibts da auch updates. Denn manchmal verändere ich gar nichts und compilierte Programme funktioniern und mal wieder nicht. Mal stürzen sie ab mal wieder nicht.

    Komisch.

    Danke dir vielmals für deine Hilfe. Jedoch wäre ich fast verrückt werden.
     

  9. #9
    Avatar von Endurion
    Endurion Endurion ist offline Mitglied Diamant
    Registriert seit
    Apr 2004
    Beiträge
    2.151
    Eher im Gegenteil, Studio .NET ist so ziemlich das Beste, was man kriegen kann. Ein paar lästige Sachen muss man halt abstellen (Dynamische Hilfe, was ein Sch***). Aber im Gegensatz zu VC6 ist es hervorragend. Man braucht leider einen bisschen fitteren Rechner dafür.
     

  10. #10
    Indian Indian ist offline Mitglied Gold
    Registriert seit
    May 2004
    Beiträge
    116
    naja,

    mir kommt es nur so vor als würde der Kompiler ein paar Fehler machen. Wie gesagt ich habs nun anderst gemacht. Jetzt muss ich noch ein paar feinarbeiten mach und denn code dokumentieren dann bin ich fertig.

    Kann man auch eine AutoDokumentation erstellen die man kürz über denn Code laufen lässt und dann eine html dokumentation erhält ? Ich dachte ich hab schon mal sowas gehört bzw. schon irgendwo gelesen ? Irgendein Tip ?
     

  11. #11
    Avatar von Endurion
    Endurion Endurion ist offline Mitglied Diamant
    Registriert seit
    Apr 2004
    Beiträge
    2.151
    Doxygen kann sowas, dummerweise sind die meisten Autodokumentierer auf ein bestimmtes Kommentarformat angewiesen.

    [edit: Das waren mehr als 60 Sekunden]
     

  12. #12
    Indian Indian ist offline Mitglied Gold
    Registriert seit
    May 2004
    Beiträge
    116
    Also hat Visual Studio NET nichts integeriert ?..


    Thx ich schau mir mal das an
     

Ähnliche Themen

  1. SMS an einen Port senden
    Von port29 im Forum Coders Talk
    Antworten: 0
    Letzter Beitrag: 01.12.08, 21:25
  2. Parameterübergabe in einen Thread
    Von DerMartin007 im Forum Java
    Antworten: 0
    Letzter Beitrag: 02.07.07, 02:18
  3. Anfrage auf einen Port
    Von Spranta im Forum PHP
    Antworten: 4
    Letzter Beitrag: 07.07.06, 03:32
  4. Programm welches Ordner überwacht und Änderungen meldet.
    Von ArFiBa im Forum Microsoft Windows
    Antworten: 1
    Letzter Beitrag: 04.03.05, 13:31
  5. Wie schreibe ich einen Thread?
    Von superharry im Forum C/C++
    Antworten: 2
    Letzter Beitrag: 22.01.05, 08:47