ERLEDIGT
NEIN
NEIN
ANTWORTEN
11
11
ZUGRIFFE
4225
4225
EMPFEHLEN
-
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; }
HILFEGeändert von Indian (29.12.04 um 11:21 Uhr)
-
29.12.04 13:05 #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
-
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.
-
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:
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 ?Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);
Kannst du mir hierbei helfen ?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;
}Geändert von Indian (30.12.04 um 09:41 Uhr)
-
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] );
-
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 ?
-
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.
-
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.
-
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.
-
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 ?
-
Doxygen kann sowas, dummerweise sind die meisten Autodokumentierer auf ein bestimmtes Kommentarformat angewiesen.
[edit: Das waren mehr als 60 Sekunden]
-
Also hat Visual Studio NET nichts integeriert ?..
Thx ich schau mir mal das an
Ähnliche Themen
-
SMS an einen Port senden
Von port29 im Forum Coders TalkAntworten: 0Letzter Beitrag: 01.12.08, 21:25 -
Parameterübergabe in einen Thread
Von DerMartin007 im Forum JavaAntworten: 0Letzter Beitrag: 02.07.07, 02:18 -
Anfrage auf einen Port
Von Spranta im Forum PHPAntworten: 4Letzter Beitrag: 07.07.06, 03:32 -
Programm welches Ordner überwacht und Änderungen meldet.
Von ArFiBa im Forum Microsoft WindowsAntworten: 1Letzter Beitrag: 04.03.05, 13:31 -
Wie schreibe ich einen Thread?
Von superharry im Forum C/C++Antworten: 2Letzter Beitrag: 22.01.05, 08:47





Zitieren
Login






