egametang/ET · error · Exception

TChannel已经被Dispose, 不能发送消息

Error message

TChannel已经被Dispose, 不能发送消息

What it means

TChannel.Send checks IsDisposed before queuing and throws if the channel's socket has been closed. This guards against use-after-free: someone is trying to send on a channel that is already torn down.

Source

Thrown at Packages/cn.etetet.core/Scripts/Core/Share/Network/TChannel.cs:97

			Log.Info($"channel dispose: {this.Id} {this.RemoteAddress} {this.Error}");
			
			long id = this.Id;
			this.Id = 0;
			this.Service.Remove(id);
			this.socket.Close();
			this.innArgs.Dispose();
			this.outArgs.Dispose();
			this.innArgs = null;
			this.outArgs = null;
			this.socket = null;
		}

		public void Send(MemoryBuffer stream)
		{
			if (this.IsDisposed)
			{
				throw new Exception("TChannel已经被Dispose, 不能发送消息");
			}
			
			switch (this.Service.ServiceType)
			{
				case ServiceType.Inner:
				{
					int messageSize = (int) (stream.Length - stream.Position);
					if (messageSize > ushort.MaxValue * 16)
					{
						throw new Exception($"send packet too large: {stream.Length} {stream.Position}");
					}

					this.sendCache.WriteTo(0, messageSize);
					this.sendBuffer.Write(this.sendCache, 0, PacketParser.InnerPacketSizeLength);
					break;
				}
				case ServiceType.Outer:
				{

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Null/clear channel references when the channel is disposed or errors out.
  2. Check IsDisposed at the call site before sending.
  3. Drive sends only through the session lifecycle that owns the channel.

Example fix

// before
channel.Send(memoryBuffer);
// after
if (channel == null || channel.IsDisposed) return;
channel.Send(memoryBuffer);
Defensive patterns

Strategy: type-guard

Validate before calling

null

Type guard

public static bool CanSend(TChannel c) => c != null && !c.IsDisposed;

Try / catch

null

Prevention

When it happens

Trigger: Application code holding a channel reference after disconnect/error and calling Send, or a send queued during shutdown racing with Dispose.

Common situations: Session not notified of channel removal, reconnect logic reusing a stale channel, or shutdown ordering where Send runs after Dispose.

Related errors


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/f35538a3c80a5841. Report an issue: GitHub.