TsgcWebSocketServer › 事件 › OnQueueDrained
当客户端连接的出站队列从有消息变为空时触发。
property OnQueueDrained: TsgcWSQueueDrainedEvent;
// TsgcWSQueueDrainedEvent = procedure(Connection: TsgcWSConnection) of object
—
仅当受影响的连接启用了消息排队时才会触发,也就是 QueueOptions.Text.Level、QueueOptions.Binary.Level 或 QueueOptions.Ping.Level 被设置为 qmNone 以外的值时。没有队列就没有需要排空的内容,此事件永远不会触发。
该处理程序在连接线程上内联运行,并且有意不通过 NotifyEvents 封送,这与本组件的其他所有事件都不同,因此它绝不能操作用户界面。这种差异是刻意为之。该事件的全部价值在于它恰好运行在连接循环的那个位置,即队列刚刚排空之后、下一次读取之前,此时套接字仍然空闲,因此应用程序可以立即发放下一份配额而无需等待。将其封送到主线程会破坏这一点。任何窗体、网格或标签的更新都必须由应用程序自行封送,可使用 TThread.Queue、TThread.Synchronize 或向主线程投递消息。
处理程序内部引发的异常会被捕获并丢弃,以确保排空过程始终能够完成。失败的处理程序不会有任何提示,因此当需要报告失败时,请在处理程序主体中自行使用 try..except 块包裹。
该事件在每次由非空变为空的转变时触发一次,而不是每次连接循环都触发一次。它并不表示某一批消息已经发送完毕。如果排空速度跟得上缓慢的生产者,那么每一条消息都可能触发各自的事件,因为每条消息都会在下一条入队之前被写出。该事件所表达的只是此连接的队列此刻为空,仅此而已。
典型用途是流量控制。当服务器在客户端之间转发大批量数据时,可使用该事件通知发送方客户端它可以继续发送。将它与 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('credit 64');
end;