Entwickler-Ecke
Windows API - Comport - Fehlendes Event (WaitFor...)
jaenicke - Fr 25.03.11 16:22
Titel: Comport - Fehlendes Event (WaitFor...)
Hallo,
wir haben hier ein Problem mit dem Ansprechen des COM Ports. Es hatte alles schon funktioniert, aber als ich es jetzt testen wollte, klappte es nicht mehr wie früher. Wenn ich WaitForMultipleObjects benutze, wird das Event nicht ausgelöst.
Der Quelltext sieht so aus:
Delphi-Quelltext
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:
| procedure ReceiveBytes(ComHandle: THandle; Overlapped: TOverlapped); var BufSize, BytesRead, Dummy: DWORD; ComStat: TComStat; begin if ClearCommError(ComHandle, Dummy, @ComStat) then begin BufSize := ComStat.cbInQue; SetLength(FLastReceived, BufSize); if ReadFile(ComHandle, FLastReceived[1], BufSize, BytesRead, @Overlapped) and (BytesRead > 0) then SendMessage(FTargetHandle, WM_DATARECEIVED, WParam(FLastReceived), 0); end; end;
var Overlapped: TOverlapped; EventMask, Dummy, SignalState: DWORD; EventHandles: array[0..1] of THandle; DCB: TDCB; TimeOut: TCommTimeouts; begin SetThreadName;
if FComHandle <> INVALID_HANDLE_VALUE then begin DCB.DCBlength := SizeOf(DCB); DCB.BaudRate := 9600; DCB.Flags := 1; DCB.wReserved := 18; DCB.XonLim := 256; DCB.XoffLim := 256; DCB.ByteSize := 8; DCB.Parity := NoParity; DCB.StopBits := 0; DCB.XonChar := #17; DCB.XoffChar := #19; DCB.ErrorChar := #0; DCB.EofChar := #0; DCB.EvtChar := #0; DCB.wReserved1 := 37563; if SetCommState(FComHandle, DCB) then begin GetCommTimeOuts(FComHandle, TimeOut);
TimeOut.ReadIntervalTimeOut := MaxInt; TimeOut.ReadTotalTimeoutMultiplier := 0; TimeOut.ReadTotalTimeoutConstant := 0;
TimeOut.WriteTotalTimeoutMultiplier := 100; TimeOut.WriteTotalTimeoutConstant := 1000; if SetCommTimeouts(FComHandle, TimeOut) then begin if SetCommMask(FComHandle, EV_RXCHAR) then begin FillChar(Overlapped, SizeOf(Overlapped), 0); Overlapped.hEvent := CreateEvent( nil, True, True, nil );
Overlapped.Internal := 0; Overlapped.InternalHigh := 0; Overlapped.Offset := 0; Overlapped.OffsetHigh := 0;
EventHandles[0] := FStopWaitingEvent; EventHandles[1] := Overlapped.hEvent; repeat WaitCommEvent(FComHandle, EventMask, @Overlapped); SignalState := WaitForMultipleObjects(2, @EventHandles, False, INFINITE); if (SignalState = WAIT_OBJECT_0 + 1) and GetOverlappedResult(FComHandle, Overlapped, Dummy, False) then ReceiveBytes(FComHandle, Overlapped); until SignalState <> (WAIT_OBJECT_0 + 1); SetCommMask(FComHandle, 0); PurgeComm(FComHandle, PURGE_TXCLEAR or PURGE_RXCLEAR); CloseHandle(Overlapped.hEvent); end; end; end; FileClose(FComHandle); end; end; |
Das Programm hängt in der markierten Zeile, das heißt das Event wird nicht ausgelöst.
Ich habe auch schon versucht nach WaitCommEvent bei Rückgabewert False mit GetLastError auf ERROR_IO_PENDING zu prüfen um direkt GetOverlappedResult zu benutzen, aber ohne Erfolg. Ich bekomme dann keine Daten, wenn ich nicht warte oder hänge dort, wenn ich warte.
Weitere Versuche:
TComPort hat das selbe Problem, eine andere Komponente, die kein WaitXXX nutzt, funktioniert. :gruebel:
Hat jemand eine Ahnung woran das liegen kann?
Vielen Dank,
schönen Gruß,
Sebastian
Delete - Fr 25.03.11 21:44
Warum WaitForMultipleObjects(2...);
jaenicke - Fr 25.03.11 22:08
Das eine Event ist das zum Abbruch des Threads, das zweite ist das Event des COM-Ports. Und die 2 gibt an, dass es sich um zwei Events handelt.
Das Abbruchevent funktioniert auch problemlos, d.h. wenn ich das Programm beende und daher mit SetEvent das Event auf Signaled setze, wird der Thread auch sauber beendet.
Delete - Fr 25.03.11 22:27
Wäre eine Variable (>0) nicht besser, die man dann mit "if SignalState =" auswertet?
jaenicke - Fr 25.03.11 23:04
Ich weiß gerade nicht genau worauf du hinaus willst, aber der Punkt ist ja nicht die Auswertung von SignalState sondern, dass das Event gar nicht ausgelöst wird.
Martok - Sa 26.03.11 00:49
EventMask ist nicht initialisiert ;)
(Warum sagt der Compiler das nicht?)
Wenn es das nicht war, ein paar Fragen die ich schon getippt hatte als es mir aufgefallen ist:
Was hast du gemacht, damit es nicht mehr geht, sprich, wie war es vorher?
Sicher, dass das Event-Handle iO ist?
Was passiert mit WaitForSingleObject?
Was bezweckst du mit dem .ReadIntervalTimeout-Wert? (Huch, das sieht mir grad am kritischsten aus)
jaenicke - Sa 26.03.11 01:00
Martok hat folgendes geschrieben : |
EventMask ist nicht initialisiert ;)
(Warum sagt der Compiler das nicht?) |
Das ist ein Out-Parameter. ;-)
Martok hat folgendes geschrieben : |
Was hast du gemacht, damit es nicht mehr geht, sprich, wie war es vorher? |
Nichts, das ist ja das Problem. Insbesondere funktioniert eben auch die TComPort-Komponente selbst nicht, deshalb ist die Frage eher welche Einflüsse / Treibereinstellungen / ... das verursachen könnten.
Martok hat folgendes geschrieben : |
Sicher, dass das Event-Handle iO ist? |
Zumindest deutet nichts darauf hin, dass es das nicht wäre. Das ist immer so ein Wert um die 300 oder so, das sollte passen. Warum sollte CreateEvent auch nicht funktionieren, so viel passiert da ja nicht.
Martok hat folgendes geschrieben : |
Was passiert mit WaitForSingleObject? |
Ich warte, dass entweder abgebrochen wird oder ein Event vom COM-Port kommt. Das prüfe ich dann mit dem SignalState.
Martok hat folgendes geschrieben : |
Was bezweckst du mit dem .ReadIntervalTimeout-Wert? (Huch, das sieht mir grad am kritischsten aus) |
Ich will ja unendlich warten, wenn nicht abgebrochen wird. Deshalb ist es auch so wichtig auf beide Events zu warten.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!