-
Люди дообрые, помогите пожалуйста разобраться с зависанием потока! 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 порта считываются некорректно, или не считываются вовсе.... ((((((((((
-
а где остальное?
-
> Если делаю остановку на условии, при отладке приложения, то все нормально не разбираясь/не видя остального поведение характерно для "кривой логики" когда изменение состояния идет событием а пишут "линейно" без "продыху" на его отработку. как проверку (НЕ РЕШЕНИЕ!) можно расставить Application.ProcessMessages в "узких" местах (а то и вообще через операцию), и если это поможет то... - переписывать по правильной логике.
-
Коды возврата функций надо проверять. Выброси свой код.
> можно расставить Application.ProcessMessages
не в тему
-
> не в тему это не по коду, это по поведению. "шаманское" наблюдение. - если переключение между процессом программы и отладчика меняет поведение программы то... а ProcessMessages самый быстрый проверочный "индикатор" (даже в потоке. уточнение, т.к. "тема" похоже определялась по этому признаку).
-
Весь юнит скинуть?
-
Ребят, плохо понимаю о чем вы говорите...
-
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 бит, а второй остальные сколько осталось. Не помню откуда брал материал, но вроде где-то на форуме....
-
> Коды возврата функций надо проверять. Выброси свой код.
-
Вроде так.... Извиняюсь, что забыл код привести в нормальный вид(((
-
А как правильно оно должно выглядеть? просто гугл как правило дает именно этот пример
-
> Ребят, плохо понимаю о чем вы говорите... мое можешь игнорировать раз не понимаешь, а Игорь вот про это- > 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.
-
получается, цикл ждет заданную маску, если видит еЁ ждет завершения потока, получает данные, отчищает буфер порта и все пихает в переменные...
-
> If not ReadFile(Port,RCBuffer[0],nToRead,nRead,@RdOvr) Then > > Else
Пробовал задавать nToRead ручками, ни чего хорошего этого не дало. Делфей нет к сожалению под рукой...
-
> Коды возврата функций надо проверять. Выброси свой код.
Да я бы может и выбросил, да заменить несем....(((
-
И как он вообще определяет nToRead?
-
> да заменить несем....((( написать?
> И как он вообще определяет nToRead? > nToRead:=ComStat.cbInQue; ???
> If nToRead = 8 Then и вот еще ошибка, заказ на считываемое количество может не совпадать с реально считанным (может тут, в частном случае, это невозможно, но не стал бы закладываться).
-
Иногда не совпадает... >nToRead:=ComStat.cbInQue Да эт понятно, я имею ввиду откуда эти данные бирутся? Можно-ли сделать, чтобы всегда одно количество было? >написать? Да, пожалуйста, если не трудно....
-
> я имею ввиду откуда эти данные бирутся? заполняются командой на строчку выше. 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
>>написать? > Да, пожалуйста, если не трудно.... нет, это ответ вопрос откуда взять... а не предложение сделать за тебя. т.е. нужно? - садись и пиши.
-
Ну тогда откуда взять)))
-
>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
Если можно, напишите понятным чайнику языком, а не цитатой из хелпа
-
И еще хотябы алгоритм действий, как оно должно выглядеть в теории, а я попробую перевести это в когд
-
Я самоучка, поэтому многого могу не понимать, будте снисходительны пожалуйста....
-
-
-
RdOvr.hEvent:=CreateEvent(nil, true, false, nil );
соответственно после того как первый раз сработало
WaitCommEvent(Port, mask, @rdOvr ); WaitForSingleObject(RdOvr.hEvent,INFINITE);
- весь твой асинхронный ввод идет лесом...
-
> FreeMem(RCBuffer,nToRead);
- стоит не в том месте. У тебя он может быть освобожден до окончания операции чтения....
> If not ReadFile(Port,RCBuffer[0],nToRead,nRead,@RdOvr) Then > Else
Код ни о чем, так как не закончен...
|