최근에는 직렬 통신을 수행하여 읽기, 쓰기 등을 담당하는 모든 Windows API 함수에 대한 간단한 인터페이스 인 클래스를 준비했습니다. 모든 I/O 작업 이 클래스 내부는 비동기 적으로 처리됩니다.중복 된 I/O 작업 중 직렬 포트 및 처리 오류
필자가 질문하기 전에 직렬 포트에서 데이터를 쓰고 읽는 방법을 보여 주겠다. (필기체의 구조가 정확히 동일하므로 프리젠 테이션에 아무런 요점도 없습니다. 둘 다).
function TSerialPort.Read(var pBuffer; const lBufferSize: Cardinal): Cardinal;
var
lOverlapped: OVERLAPPED;
lLastError: Cardinal;
lEvent: TEvent;
begin
lEvent := TEvent.Create(nil, True, False, '');
try
FillChar(lOverlapped, SizeOf(lOverlapped), 0);
lOverlapped.hEvent := lEvent.Handle;
if not ReadFile(FSerialPortHandle, pBuffer, lBufferSize, Result, @lOverlapped) then
begin
lLastError := GetLastError;
if (lLastError <> ERROR_IO_PENDING) and (lLastError <> ERROR_SUCCESS) then
raise Exception.Create(SysErrorMessage(lLastError));
case lEvent.WaitFor(INFINITE) of
wrSignaled:
if not GetOverlappedResult(FSerialPortHandle, lOverlapped, Result, False) then
raise Exception.Create(SysErrorMessage(GetLastError));
wrError:
begin
lLastError := lEvent.LastError;
//this is a call to Windows.CancelIo(FSerialPortHandle);
if Self.CancelIO() then
lEvent.WaitFor(INFINITE);
raise Exception.Create(SysErrorMessage(lLastError));
end;
end;
end;
finally
FreeAndNil(lEvent);
end;
end;
이 기능이 완료 될 때까지 읽기 작업을 기다리는 동안은 중복 작업에 시리얼 포트를 열 왜 나 한테 물어 전에
가 여기 내 설명입니다 - 직렬 포트를 여는 경우에만이 방법은 내가 시간 WaitCommEvent을 (지정할 수 있습니다) 방법 이벤트를 기다린다. 겹치지 않는 작업을 위해 포트를 열면 직렬 포트에 이벤트가 나타날 때까지 WaitCommEvent()가 차단되어 항상 호출 스레드가 영원히 차단되지 않을 수 있습니다.그럼에도 불구하고, 위의 Read() 함수에 집중하겠습니다.
1) 우선 이벤트를 설정할 시간 제한없이 대기합니다. 거기 때문에 현재 스레드가 그 이유 때문에 영원히 차단 될 가능성이 있습니까? 나는 비동기 적으로 읽기 작업을 수행하는 스레드에 의해 이벤트가 조만간 설정 될지 100 % 확신 할 수 있는지 여부를 알지 못합니다. 직렬 포트의 읽기 타임 아웃이 모두 0으로 설정되면 주어진 바이트 수를 읽을 때까지 읽기 작업이 완료되지 않는다는 것을 알고 있습니다. 그러나 이것은 제가 알고있는 동작입니다. 내 질문에 이벤트가 설정되지 않을 것입니다 예기치 않은 상황과 WaitFor() 메서드를 영원히 기다릴 우려 - 그것은 일어날 가능성이 높습니다?
2) WaitFor()는 대기 작업 중 일부 오류가 발생했음을 알리는 wrError를 반환 할 수 있습니다 (단, 중복 된 읽기 작업과 연결되지는 않습니다). 따라서 더 이상 읽을 작업이 끝날 때까지 기다릴 필요가 없다고 생각합니다. 이벤트 핸들이 더 이상 사용할 수 없기 때문입니다. 맞습니까? 그래서 CancelIO() 메서드를 호출하여 읽기 작업을 취소하고 비동기 적으로 취소 된 읽기를 수행 한 스레드가 이벤트를 설정하고 예외를 발생시킬 때까지 기다립니다. 내가 그 스레드에 의해 취소 될 때까지 기다릴 것이기 때문에 나는 (Read/Write) I/O를 취소하지 않고 즉시 Read() 메소드를 떠났기 때문에, 그 쓰레드가 그 데이터 (겹쳐진 레코드 데이터)를 로컬 변수에 쓰게 할 것이다. 더 이상 유효하지 않아요, 그렇죠? 한편, 예외를 발생시키기 전에 WaitFor (INFINITE) 호출로 인해 현재 스레드가 영구적으로 차단 될 위험이 있습니까?
위의 진술이 사실인지 아닌지 알려 주시면 의견을 보내 주시면 감사하겠습니다.
대단히 감사합니다.
제안 해 주셔서 감사합니다.당신 말이 맞을지 모르지만 나는 여전히 내 질문에 대한 답을 알고 싶다. 그것은 나의 호기심이나 오히려 그 주제에 대한 나의 지식을 넓히고 싶다. –