Endloseschleife innerhalb eines Threads?
-
Erstmal vielen Dank für Eure Antworten, das hat mir schon sehr weitergeholfen. WaitCommEvent hört sich sehr gut an, wenn ich das aber richtig verstanden habe, muss ich das auch in einer Schleife einsetzen, damit meine Anwendung permanent auf den Port hört, oder? Der Vorteil hierbei ist aber, dass es weitaus weniger Schleifendurchläufe gibt, da der Thread nicht läuft, wenn kein Signal von der Schnittstelle kommt. Hab ich das alles richtig verstanden?
-
Nein, WaitCommEvent wartet (genauso wie WaitForSingleObject u.ä.) so lange, bis etwas "passiert" (ein Event signalisiert wird). Passiert nix, wacht Dein Thread auch nicht auf!
Zitat MSDN:
If hFile was not opened with FILE_FLAG_OVERLAPPED, WaitCommEvent does not return until one of the specified events or an error occurs.Also, COM-Schnittstelle NICHT OVERLAPPED öffnen, dann wird Dein Thread so lange blockiert bis etwas passiert und Du drauf reagieren kannst...
Nix Schleife....
-
Aber so wie ich ihn verstanden habe braucht er weiterhin eine Schleife, da er ja nachdem etwas passiert ist noch weiter auf Daten warten will
Würde es eigentlich mit ReadFile (also ohne WaitCommEvent) nicht auch direkt gehen?
-
flenders schrieb:
Würde es eigentlich mit ReadFile (also ohne WaitCommEvent) nicht auch direkt gehen?
kommt drauf an was er machen will
-
mit WaitCommEvent warten sollte kein problem sein, wenn er EV_BREAK mit in der
Eventmaske hat kann er vom kontrol-thread ein 'SetCommBreak' an den port senden
und seinen empfangs-thread 'ordentlich' beenden
-
Hallo,
WaitCommEvent ist ein bisschen tricky, so leicht es sich anfangs auch anhört. Wenn Du das benutzen willst, solltest Du auf jeden Fall die MSDN lesen und diesen Artikel: http://codeproject.com/system/serial_com.aspDesweiteren empfehle ich für die Grundlagen:
http://www.lookrs232.com/com_port_programming
Beachte besonders das PurgeComm() - das vergisst man leicht und dann geht gar nichts mehr.Meiner Meinung nach solltest Du WaitCommEvent nur benutzen, wenn nicht andauernd Daten vom ComPort kommen und du diese eh immer lesen musst. Dann reicht auch das einfache "Polling-Verfahren" - also, permanent lesen vom COM-Port. Das wäre im Prinzip dasselbe, weil WaitCommEvent dann auch die ganze Zeit Events abfeuern würde. Natürlich musst Du dann darauf achten, dass Dein Lese-Thread nicht andauernd mehr Speicher verbraucht. Auch ein kleines Sleep( 0 ) oder Sleep( 1 ) am Ende der Thread-Schleife wirkt Wunder beim Polling-Verfahren.
-
So, erstmal vielen Dank für Eure Hilfe, das hat mir schon sehr weitergeholfen. Ich muss tatsächlich permanent von der seriellen Schnittstelle lesen, weshalb ich nicht WaitCommEvent, sondern nur ReadFile innerhalb einer Schleife verwende. Allerdings empfange ich keine Daten. Obwohl das Gerät sendet, kommt bei mir im Buffer nichts an.
Ich poste Euch mal den Quellcode, vielleicht könnt Ihr mir helfen://thread function; opens com port and reads data from it DWORD WINAPI receiveGPSData(LPVOID lParam) { short* rec = (short*)lParam; wchar_t* data = new wchar_t[2048]; wchar_t* port_str = new wchar_t[6]; wchar_t* msg = new wchar_t[100]; DCB dcb; COMMTIMEOUTS cto; DWORD bytesread=0, mask=0; swprintf(port_str,L"COM%d:",port); //establish connection to serial port hComPort = CreateFile (port_str,GENERIC_READ,0,0,OPEN_EXISTING,0,0); if(GetCommState(hComPort,&dcb)) { //set com port state dcb.BaudRate = CBR_4800; dcb.Parity = NOPARITY; dcb.StopBits = 1; dcb.ByteSize = 8; if(!SetCommState(hComPort,&dcb)) MessageBox(NULL,L"Fehler beim Setzen der Port-Einstellungen",L"Achtung",MB_OK | MB_ICONERROR | MB_APPLMODAL); } if(GetCommTimeouts(hComPort,&cto)) { //set com port timeouts cto.ReadIntervalTimeout = 200; cto.ReadTotalTimeoutConstant = 200; cto.ReadTotalTimeoutMultiplier = 200; if(!SetCommTimeouts(hComPort,&cto)) MessageBox(NULL,L"Fehler beim Setzen der Timeout-Eigenschaften",L"Achtung",MB_OK | MB_ICONERROR | MB_APPLMODAL); } if(hComPort != INVALID_HANDLE_VALUE) { while(*rec) { wcscpy(data,L""); ReadFile(hComPort,&data,wcslen(data),&bytesread,NULL); PurgeComm(hComPort,PURGE_TXCLEAR|PURGE_RXCLEAR); if(bytesread>0) { wcscpy(msg,L""); swprintf(msg,L"%s",data); MessageBox(NULL,msg,L"Achtung",MB_OK); } Sleep(1); } CloseHandle(hComPort); } delete data; delete port_str; return 0; }
Das Problem ist nun, dass data immer leer bleibt. In die Schleife "if(bytesread>0)" springt er also nie rein.
Die Variable rec wird außen von geändert, wenn der Thread beendet werden soll, das funktioniert auch einwandfrei.Vielen Dank für Eure Hilfe!
-
wcslen(data) gibt 0 zurück, d.h. du forderst 0 Bytes an.
Empfehlenswert ist auch, den Rückgabewert von ReadFile zu prüfen, und ggf. GetLastError aufzurufen.
Nachtrag:
&data ist auch falsch, data ist schon ein Zeiger.Außerdem musst du Arrays mit delete[] freigeben.
-
Daran lags, tatsächlich !!!!! Vielen Dank, das Problem war "&data", wie kann man nur so blöd sein
-
Hi,
und nimm das PurgeComm() aus der Read-Schleife raus. Das muss bloß einmal beim ersten Öffnen gemacht werden.