TsgcWebSocketClient › 이벤트 › OnQueueDrained
송신 메시지 큐에 메시지가 있다가 비어 있는 상태로 바뀔 때 발생합니다.
property OnQueueDrained: TsgcWSQueueDrainedEvent;
// TsgcWSQueueDrainedEvent = procedure(Connection: TsgcWSConnection) of object
—
메시지 큐잉이 활성화되어 있을 때만, 즉 QueueOptions.Text.Level, QueueOptions.Binary.Level 또는 QueueOptions.Ping.Level이 qmNone 이외의 값으로 설정되어 있을 때만 발생합니다. 큐가 없으면 비울 것도 없으므로 기본 qdmTransition 모드에서는 이벤트가 발생하지 않습니다.
핸들러는 연결 스레드에서 인라인으로 실행되며, 이 컴포넌트의 다른 모든 이벤트와 달리 의도적으로 NotifyEvents를 통해 마샬링되지 않으므로 사용자 인터페이스를 건드려서는 안 됩니다. 이러한 차이는 의도된 것입니다. 이 이벤트의 가치는 전적으로 연결 루프의 바로 그 지점, 즉 큐가 비워진 직후이자 다음 읽기 전이며 소켓이 아직 유휴 상태일 때 실행된다는 데 있고, 그래서 애플리케이션이 기다리지 않고 다음 청크를 내보낼 수 있습니다. 이를 메인 스레드로 마샬링하면 그 이점이 사라집니다. 폼, 그리드, 레이블 갱신은 애플리케이션이 TThread.Queue, TThread.Synchronize 또는 메인 스레드로 보내는 메시지를 사용하여 직접 마샬링해야 합니다.
핸들러 내부에서 발생한 예외는 포착되어 무시되므로 큐 비우기는 항상 완료됩니다. 실패한 핸들러는 아무런 알림 없이 조용히 실패하므로, 실패를 보고해야 한다면 본문을 자체 try..except 블록으로 감싸십시오.
QueueOptions.DrainedMode 속성이 이벤트가 발생하는 시점을 선택합니다. qdmTransition(기본값)에서는 아래에 설명하는 대로 비어 있지 않은 상태에서 비어 있는 상태로 전환될 때마다 한 번 발생합니다. qdmEveryPass에서는 큐가 이미 비어 있었더라도, 그리고 Text.Level, Binary.Level, Ping.Level이 모두 qmNone이더라도, 큐를 전송한 직후 연결 루프의 매 회차마다 발생하므로 임시 큐 수준이 필요하지 않습니다. 이 모드에서 핸들러는 연결 스레드의 연결별 후크이며, 예를 들어 WriteData로 대기 중인 애플리케이션 데이터를 보내면 연결에 대한 모든 쓰기가 그 연결 자신의 스레드에서 이루어집니다(Binary.Level이 qmNone이면 이벤트 안의 WriteData는 소켓에 직접 씁니다). 전환 모드와 마찬가지로 인라인으로 실행되며 NotifyEvents를 따르지 않으므로 핸들러는 빨라야 하며 사용자 인터페이스를 건드려서는 안 됩니다. 각 연결은 연결할 때 큐 옵션을 복사하므로 컴포넌트를 활성화하기 전에 DrainedMode를 설정하십시오. 이미 열린 연결은 이전 모드를 유지합니다.
qdmTransition 모드에서 이 이벤트는 연결 루프의 각 회차마다가 아니라 큐가 비어 있지 않은 상태에서 비어 있는 상태로 전환될 때마다 한 번 발생합니다. 버스트가 끝났다는 신호가 아닙니다. 큐 비우기가 느린 생산자를 따라잡으면 각 메시지가 다음 메시지가 큐에 들어가기 전에 전송되기 때문에 모든 메시지가 각각 자신의 이벤트를 발생시킬 수 있습니다. 이 이벤트가 알려주는 것은 지금 이 연결의 큐가 비어 있다는 사실뿐이며 그 이상은 아닙니다.
일반적인 용도는 흐름 제어입니다. 클라이언트가 대량 데이터를 스트리밍할 때 이 이벤트를 사용하여 다음 청크를 내보내면, 생산자가 메모리를 채우는 대신 소켓의 속도에 맞추어 진행됩니다. 해당 연결에 아직 큐에 남아 있는 메시지 수를 알려주는 TsgcWSConnection의 PendingCount 속성과 함께 사용하면 정지 후 대기 방식 대신 크레딧 윈도 방식을 구현할 수 있습니다.
관리형 .NET 포팅도 동일한 의미의 같은 이벤트를 발생시킵니다. 유일한 차이는 이벤트가 도착하는 빈도입니다. Delphi의 큐 비우기는 연결 루프의 각 회차마다 한 번 실행되며 그 간격은 Options.ReadTimeOut 밀리초로 기본값은 10입니다. 따라서 메시지가 느리게 조금씩 들어오면 적은 수의 이벤트로 합쳐집니다. 관리형 큐 비우기는 이벤트 기반이므로 동일한 흐름에서도 더 많은 이벤트가 발생할 수 있습니다. 버스트의 동작은 양쪽이 동일합니다.
procedure OnQueueDrained(Connection: TsgcWSConnection);
begin
// runs on the connection thread, do not touch the user interface here
Connection.WriteData(GetNextChunk);
end;
// qdmEveryPass: runs on every pass of the connection loop
oClient.QueueOptions.DrainedMode := qdmEveryPass;
oClient.QueueOptions.Ping.Level := qmLevel1;
procedure OnQueueDrained(Connection: TsgcWSConnection);
begin
// runs on the connection thread, do not touch the user interface here
if Connection.Disconnected then
exit;
if HasPendingData then
Connection.WriteData(GetPendingData);
end;