Autor Beitrag
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 25.03.11 16:22 
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:
ausblenden volle Höhe 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, // Port handle
        FLastReceived[1],    // Pointer to data to read
        BufSize,             // Number of bytes to read
        BytesRead,           // Pointer to number of bytes read
        @Overlapped)         // Overlapped structure
        and (BytesRead > 0then
        SendMessage(FTargetHandle, WM_DATARECEIVED, WParam(FLastReceived), 0);
    end;
  end;

var
  Overlapped: TOverlapped;
  EventMask, Dummy, SignalState: DWORD;
  EventHandles: array[0..1of THandle;
  DCB: TDCB;
  TimeOut: TCommTimeouts;
begin
  SetThreadName;

  if FComHandle <> INVALID_HANDLE_VALUE then
  begin
    DCB.DCBlength := SizeOf(DCB);
    DCB.BaudRate := 9600;
    DCB.Flags := 1// binary --> set always
    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
         // Set the event mask.
        if SetCommMask(FComHandle, EV_RXCHAR) then
        begin
          // Create an event object for use by WaitCommEvent.
          FillChar(Overlapped, SizeOf(Overlapped), 0);
          Overlapped.hEvent := CreateEvent(
            nil,    // default security attributes
            True,   // manual-reset event
            True,   // not signaled
            nil     // no name
          );

          // Initialize the rest of the OVERLAPPED structure to zero.
          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
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Fr 25.03.11 21:44 
Warum WaitForMultipleObjects(2...);
jaenicke Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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.
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Fr 25.03.11 22:27 
Wäre eine Variable (>0) nicht besser, die man dann mit "if SignalState =" auswertet?
jaenicke Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: 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)

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
jaenicke Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 26.03.11 01:00 
user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
EventMask ist nicht initialisiert ;)
(Warum sagt der Compiler das nicht?)
Das ist ein Out-Parameter. ;-)

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
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.
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Sa 26.03.11 01:36 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
EventMask ist nicht initialisiert ;)
(Warum sagt der Compiler das nicht?)
Das ist ein Out-Parameter. ;-)

Upps.

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
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.

Das meinte ich nicht... was passiert, wenn du nur WFSingleO verwendest? Vielleicht ist ja das Array komisch, meine Erfahrung, dass spontan auftretende Probleme immer was mit Memory Corruption zu tun haben wurde ja neulich wieder bestätigt.

Ansonsten: was ist denn für den Port konfiguriert? Irgendwelche Zwangs-Buffer, die erst in dröflzig Tagen voll werden?

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."