Существует некоторая программа обчитывающая приборы по средствам преобразователя RS485->COM порт. Так вот по непонятным причинам порт иногда подвисает и начинает работать только после перезапуска приложения хотя работа с портом вынесена в отдельный поток, который я в основном приложении пытался пересоздать.
TAPIComPort = class(TThread)
private
Port: THandle;
Status: Boolean;
protected
procedure Execute; override;
public
FComNo: string;
FBaudRate: integer;
FerrPort: Boolean;
constructor Create;
function Open(AComNo: string; ABaudRate: integer): Boolean;
procedure Read(Var buf: TArrayByte; var Count: Cardinal);
procedure Write(TRBuf: PAnsiChar; Count: integer);
Function Close(): Boolean;
destructor Destroy;
end;
// если завис
port.Terminate;
FreeAndNil(port); // на всякий случай
Sleep(100);
port := TAPIComPort.Create;
if port.Open(cComNom, cBuadRate) then
begin
....
Так вот смоделировать ситуацию при которой порт не открылся бы заново у меня не получается (т.е. даже при отключении преобразователя и пропадании порта из системы всё корректно отрабатывает и при его появлении все процессы востанавливаются автоматически)
На производстве же
port.Open(cComNom, cBuadRate)
отрабатывать отказывается. И всё начинает работать после полного перезапуска модуля.
function TAPIComPort.Open(AComNo: string; ABaudRate: integer): Boolean;
Var
DCB: TDCB; // структура, содержащая настройки порта
CommTimeouts: TCommTimeouts;
begin
FComNo := AComNo;
FBaudRate := ABaudRate;
Port := CreateFile(PWideChar('\\.\COM' + AComNo), // открываем первый порт
GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (Port = INVALID_HANDLE_VALUE) // если порт не окрылся
then
begin
result := False; // то выводим сообщение об ошибке
Exit;
end
else
result := True; // Если порт открылся, то пишем что открылся
Windows.SetupComm(Port, 1024, 1024);
Status := not result;
GetCommState(Port, DCB);
// что бы не заполнять всю структуру самим, сначал считываем ее, потом поменяем нужные поля
DCB.BaudRate := ABaudRate; // скорость обмена
DCB.Parity := NoParity; // нет контроля четности
DCB.ByteSize := 8; // байт из восьми бит
DCB.StopBits := ONESTOPBIT; // один стоповый бит
SetCommState(Port, DCB);
// записываем измененную структуру, для открытого порта
GetCommTimeouts(Port, CommTimeouts);
CommTimeouts.ReadTotalTimeoutConstant := 50;
CommTimeouts.ReadIntervalTimeout := 50;
CommTimeouts.ReadTotalTimeoutMultiplier := 1;
CommTimeouts.WriteTotalTimeoutMultiplier := 0;
CommTimeouts.WriteTotalTimeoutConstant := 10;
// операции записи не используется.
SetCommTimeouts(Port, CommTimeouts); // записываем измененную структуру
FerrPort := not result;
end;
Может у кого есть соображения по поводу, желательно без перезапуска приложения самого из себя?