Skip to content

Commit 8c8a428

Browse files
authored
Merge pull request #17 from Sendspin/task/fix-event-subscription-leak
Fix event subscription leak in SendspinClientService (C8)
2 parents c84c42c + f170300 commit 8c8a428

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

src/Sendspin.SDK/Client/SendSpinClient.cs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace Sendspin.SDK.Client;
1313
/// <summary>
1414
/// Main Sendspin client that orchestrates connection, handshake, and message handling.
1515
/// </summary>
16-
public sealed class SendspinClientService : ISendspinClient
16+
public sealed class SendspinClientService : ISendspinClient, IDisposable
1717
{
1818
private readonly ILogger<SendspinClientService> _logger;
1919
private readonly ISendspinConnection _connection;
@@ -1065,12 +1065,27 @@ private void OnBinaryMessageReceived(object? sender, ReadOnlyMemory<byte> data)
10651065
}
10661066
}
10671067

1068+
/// <summary>
1069+
/// Synchronous dispose — unsubscribes connection events to break the reference
1070+
/// cycle that prevents GC when <see cref="DisposeAsync"/> is not called.
1071+
/// Prefer <see cref="DisposeAsync"/> for full cleanup including async operations.
1072+
/// </summary>
1073+
public void Dispose()
1074+
{
1075+
if (_disposed) return;
1076+
_disposed = true;
1077+
1078+
StopTimeSyncLoop();
1079+
UnsubscribeConnectionEvents();
1080+
}
1081+
10681082
public async ValueTask DisposeAsync()
10691083
{
10701084
if (_disposed) return;
10711085
_disposed = true;
10721086

10731087
StopTimeSyncLoop();
1088+
UnsubscribeConnectionEvents();
10741089

10751090
// NOTE: We do NOT dispose _audioPipeline here - it's a shared singleton
10761091
// managed by the DI container. We only stop playback if active.
@@ -1079,10 +1094,13 @@ public async ValueTask DisposeAsync()
10791094
await _audioPipeline.StopAsync();
10801095
}
10811096

1097+
await _connection.DisposeAsync();
1098+
}
1099+
1100+
private void UnsubscribeConnectionEvents()
1101+
{
10821102
_connection.StateChanged -= OnConnectionStateChanged;
10831103
_connection.TextMessageReceived -= OnTextMessageReceived;
10841104
_connection.BinaryMessageReceived -= OnBinaryMessageReceived;
1085-
1086-
await _connection.DisposeAsync();
10871105
}
10881106
}

0 commit comments

Comments
 (0)