TsgcWebTransportSession › Events › OnClose
Fires when Close is called on the session. In Delphi and C++Builder that only ever happens because your own code called it.
property OnClose: TsgcWebTransportNotifyEvent read FOnClose write FOnClose;
// event type
TsgcWebTransportNotifyEvent = procedure(Sender: TObject) of object;
// handler signature
procedure MySessionClose(Sender: TObject);
| Name | Type | Description |
|---|---|---|
Sender | TObject | The TsgcWebTransportSession that is closing. Cast it when you need the session's SessionId or streams. |
The C# handler additionally receives an EventArgs parameter, which is always EventArgs.Empty and carries no information.
Unassigned. When no handler is assigned, Close still marks the session closed and closes the streams still open on it.
When it fires. Only from Close, and Close is not called by the Delphi or C++Builder HTTP/3 client or server. So in practice this event fires exactly when your own code calls oSession.Close. It is a local signal you send yourself, not a notification from the network. Nothing raises it when the peer goes away, when the QUIC connection drops, or when the session is destroyed.
If you need to know that a session really ended, watch the client's connection-level events instead, or track the loss of your streams.
The session is still fully valid inside the handler. Close does not free the session and does not deregister it, so you can safely read SessionId or call any method. It has, however, already closed the session's streams by the time this event runs, so each of their OnClose handlers has fired and StreamCount is 0. The stream objects themselves stay alive and readable until the session is destroyed. Treat the session as finished once you have closed it, and stop writing to it.
Close is guarded against repeat calls, so this event fires at most once per session, even if Close is called again from inside the handler.
Threading. The event runs on whichever thread called Close, with no synchronisation of its own. If that is a background thread and your handler touches the UI, marshal with TThread.Synchronize or TThread.Queue.
.NET difference, and it is a real one. On the managed stack the client does call Close for you. A background task drains the CONNECT stream, and when the server closes or drops it, that task removes the session from the registry and calls Close. So on .NET OnClose doubles as a genuine peer-disconnect notification, and it fires on a thread-pool thread. Code written against the Delphi behaviour should not assume the event will arrive on its own, and code written against the .NET behaviour should not assume it will not. What Close itself does matches on every stack: it closes the session's open streams before raising this event, and it is guarded against repeat calls.
// Assign right after the session is created, on either side
procedure TfrmClient.btnConnectClick(Sender: TObject);
begin
FSession := FClient.WebTransportConnect('https://127.0.0.1:4433/echo');
if Assigned(FSession) then
FSession.OnClose := OnSessionClose;
end;
procedure TfrmClient.OnSessionClose(Sender: TObject);
var
oSession: TsgcWebTransportSession;
begin
oSession := TsgcWebTransportSession(Sender);
// The session is still valid here, so its state can be inspected
memoLog.Lines.Add(Format('session %d closed after %d streams',
[oSession.SessionId, oSession.StreamCount]));
// Release only OUR state; the session is owned by the client
tmrPump.Enabled := False;
FStream := nil;
end;