// Code simplified for demonstration public class TsClientRepository : ITeamSpeakClientRepository { private readonly Dictionary<Guid, ITeamSpeakClient> clients = new Dictionary<Guid, ITeamSpeakClient>(); private readonly object clientsLock = new object(); private readonly IServiceScopeFactory serviceScopeFactory; private readonly ILoggerFactory loggerFactory; public TsClientRepository(IServiceScopeFactory serviceScopeFactory, ILoggerFactory loggerFactory) { this.serviceScopeFactory = serviceScopeFactory; this.loggerFactory = loggerFactory; } public async Task CreateClientAsync(ServerConfig config) { var logger = loggerFactory.CreateLogger<TSClient>(); var client = new TSClient(config, serviceScopeFactory, logger); // Discard the task since it will run forever // unless Dispose is called _ = InitClientAsync(client); lock (clientsLock) { clients.Add(config.Id, client); } } private static async Task InitClientAsync(TSClient client) { // Starts a Task which will run forever await client.ConnectAsync(); await client.SubscribeToClientChangesAsync(); } // Stops the client by Disposing it and removing the reference to the object public void RemoveClient(Guid serverId) { if (clients.ContainsKey(serverId)) { var client = clients[serverId]; lock (clientsLock) { clients.Remove(serverId); } client.Dispose(); } } }