// 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();
        }
    }
}