Конференция "WinAPI" » Проблема с потоком [D7, WinXP]
 
  • defen2204 (01.02.13 11:31) [0]
    Люди дообрые, помогите пожалуйста разобраться с зависанием  потока!
    Procedure RDthread.Execute;
    var
    i:integer;
    Begin
     i2:=0;

      FillChar(RdOvr,SizeOf(TOverlapped),0);
      RdOvr.hEvent:=CreateEvent(nil,
      true,
      false,
      nil
      );

      SetCommMask(Port,
      EV_RXFLAG);
     while not Terminated Do Begin
     WaitCommEvent(Port,
     mask,
     @rdOvr
     );
    FreeMem(RCBuffer,nToRead);
    WaitForSingleObject(RdOvr.hEvent,INFINITE);
    GetOverlappedResult(Port,RdOvr,nRead,false);
    ClearCommError(Port,Errs,@ComStat);
    nToRead:=ComStat.cbInQue;
    GetMem(RcBuffer,nToRead);
    If not ReadFile(Port,RCBuffer[0],nToRead,nRead,@RdOvr) Then
    Else



    Если делаю остановку на условии, при отладке приложения, то все нормально, а вот если убираю, то данные с com порта считываются некорректно, или не считываются вовсе.... ((((((((((
  • brother © (01.02.13 11:41) [1]
    а где остальное?
  • sniknik © (01.02.13 12:51) [2]
    > Если делаю остановку на условии, при отладке приложения, то все нормально
    не разбираясь/не видя остального поведение характерно для "кривой логики" когда изменение состояния идет событием а пишут "линейно" без "продыху" на его отработку. как проверку (НЕ РЕШЕНИЕ!) можно расставить Application.ProcessMessages в "узких" местах (а то и вообще через операцию), и если это поможет то... - переписывать по правильной логике.
  • Игорь Шевченко © (01.02.13 13:43) [3]
    Коды возврата функций надо проверять. Выброси свой код.


    > можно расставить Application.ProcessMessages


    не в тему
  • sniknik © (01.02.13 13:59) [4]
    > не в тему
    это не по коду, это по поведению. "шаманское" наблюдение. - если переключение между процессом программы и отладчика меняет поведение программы то... а ProcessMessages самый быстрый проверочный "индикатор" (даже в потоке. уточнение, т.к. "тема" похоже определялась по этому признаку).
  • Defen2204 (01.02.13 14:07) [5]
    Весь юнит скинуть?
  • Defen2204 (01.02.13 14:09) [6]
    Ребят, плохо понимаю о чем вы говорите...
  • defen2204 (01.02.13 14:20) [7]
    unit ReadPort;
    interface

    uses
     Classes,Windows, Messages, SysUtils, Variants, Graphics, Controls, Forms,
     Dialogs, StdCtrls, ComCtrls, ExtCtrls;

     type
     RdThread = class(TThread)
     Private
     Protected
     Procedure Execute; override;

    //  Procedure UpdateGenFormnReadLabel;
     End;
    var
    RC: array [1..38]of byte;
    i2:integer;

    implementation
    uses Gen;
    Var
    RCBuffer:Array of Byte;
     
    nToRead:Cardinal;
    nRead:Cardinal;
    ComStat:TcomStat;
    Errs:Cardinal;
    RdOvr:TOverlapped;
    Mask:DWord;

    Procedure RDthread.Execute;
    var
    i:integer;
    Begin
     i2:=0;

      FillChar(RdOvr,SizeOf(TOverlapped),0);
      RdOvr.hEvent:=CreateEvent(nil,
      true,
      false,
      nil
      );

      SetCommMask(Port,
      EV_RXFLAG);
     while not Terminated Do Begin
     WaitCommEvent(Port,
     mask,
     @rdOvr
     );
    FreeMem(RCBuffer,nToRead);
    WaitForSingleObject(RdOvr.hEvent,INFINITE);
    GetOverlappedResult(Port,RdOvr,nRead,false);
    ClearCommError(Port,Errs,@ComStat);
    nToRead:=ComStat.cbInQue;
    GetMem(RcBuffer,nToRead);
    If not ReadFile(Port,RCBuffer[0],nToRead,nRead,@RdOvr) Then
    Else

     If nToRead = 8 Then
     Begin
      For i:=0 to nToRead-1 do
       Begin
       i2:=i2+1;
       RC[i2]:=RCBuffer[i];
       end;
       end
        Else
        Begin
        If nToRead = 31 Then
        Begin
        i2:=8;
          For i:=0 to nToRead-1 do

       Begin
       i2:=i2+1;
       RC[i2]:=RCBuffer[i];
       Gen.GenForm.Label4.Caption:=IntToStr(i2);
       end;
         Begin
         i2:=0;
         Gen.PortDataRecived;
         End;
         End;
         end;
         i2:=0;
         End;

    End;
    end.

    процедура не доработана, так как нет стабильного получения данных. nToRead переменная указывающая количество бит для чтения с СОМ порта. По идее, она получает количество пришедших бит и передает значение на считывание непосредственно данных. Но почему-то считывание происходит блоками. Первый 8 бит, а второй остальные сколько осталось. Не помню откуда брал материал, но вроде где-то на форуме....
  • Игорь Шевченко © (01.02.13 14:21) [8]

    > Коды возврата функций надо проверять. Выброси свой код.
  • defen2204 (01.02.13 14:25) [9]
    Вроде так.... Извиняюсь, что забыл код привести в нормальный вид(((
  • defen2204 (01.02.13 14:26) [10]
    А как правильно оно должно выглядеть? просто гугл как правило дает именно этот пример
  • sniknik © (01.02.13 14:29) [11]
    > Ребят, плохо понимаю о чем вы говорите...
    мое можешь игнорировать раз не понимаешь, а Игорь вот про это-
    > WaitForSingleObject(RdOvr.hEvent,INFINITE);
    If the function succeeds, the return value indicates the event that caused the function to return.
    If the function fails, the return value is WAIT_FAILED. To get extended error information, call GetLastError.

    ...
    см хелп по каждой функции
    ...
    > If not ReadFile(Port,RCBuffer[0],nToRead,nRead,@RdOvr) Then
    > Else
    If a named pipe is being read in message mode and the next message is longer than the nNumberOfBytesToRead parameter specifies, ReadFile returns FALSE and GetLastError returns ERROR_MORE_DATA. The remainder of the message may be read by a subsequent call to the ReadFile or PeekNamedPipe function.
  • defen2204 (01.02.13 14:35) [12]
    получается, цикл ждет заданную маску, если видит еЁ ждет завершения потока, получает данные, отчищает буфер порта и все пихает в переменные...
  • defen2204 (01.02.13 14:40) [13]

    > If not ReadFile(Port,RCBuffer[0],nToRead,nRead,@RdOvr) Then
    > > Else

    Пробовал задавать nToRead ручками, ни чего хорошего этого не дало. Делфей нет к сожалению под рукой...
  • defen2204 (01.02.13 14:42) [14]

    > Коды возврата функций надо проверять. Выброси свой код.

    Да я бы может и выбросил, да заменить несем....(((
  • defen2204 (01.02.13 14:45) [15]
    И как он вообще определяет nToRead?
  • sniknik © (01.02.13 15:11) [16]
    > да заменить несем....(((
    написать?

    > И как он вообще определяет nToRead?
    > nToRead:=ComStat.cbInQue;
    ???

    > If nToRead = 8 Then
    и вот еще ошибка, заказ на считываемое количество может не совпадать с реально считанным (может тут, в частном случае, это невозможно, но не стал бы закладываться).
  • Defen2204 (01.02.13 15:35) [17]
    Иногда не совпадает...
    >nToRead:=ComStat.cbInQue
    Да эт понятно, я имею ввиду откуда эти данные бирутся? Можно-ли сделать, чтобы всегда одно количество было?
    >написать?
    Да, пожалуйста, если не трудно....
  • sniknik © (01.02.13 16:43) [18]
    > я имею ввиду откуда эти данные бирутся?
    заполняются командой на строчку выше.
    The ClearCommError function retrieves information about a communications error and reports the current status of a communications device. The function is called when a communications error occurs, and it clears the device's error flag to enable additional input and output (I/O) operations

    >>написать?
    > Да, пожалуйста, если не трудно....
    нет, это ответ вопрос откуда взять... а не предложение сделать за тебя. т.е. нужно? - садись и пиши.
  • Defen2204 (01.02.13 16:45) [19]
    Ну тогда откуда взять)))
 
Конференция "WinAPI" » Проблема с потоком [D7, WinXP]
Есть новые Нет новых   [134430   +4][b:0][p:0.001]