public async Task <ITransport <AmpMessage> > CreateTransport(EndPoint endpoint) { if (this.TRANSPORT_CACHE.TryGetValue(endpoint, out var transport)) { return(transport); } await semaphoreSlim.WaitAsync(); try { if (this.TRANSPORT_CACHE.TryGetValue(endpoint, out transport)) { return(transport); } var context = await this._socket.ConnectAsync(endpoint); transport = new DefaultTransport(context); this.TRANSPORT_CACHE.AddOrUpdate(endpoint, transport, (k, old) => { //Dispose old.CloseAsync(CancellationToken.None).AnyContext(); return(transport); }); return(transport); } finally { //When the task is ready, release the semaphore. It is vital to ALWAYS release the semaphore when we are ready, or else we will end up with a Semaphore that is forever locked. //This is why it is important to do the Release within a try...finally clause; program execution may crash or take a different path, this way you are guaranteed execution semaphoreSlim.Release(); } }
public ITransport <TMessage> CreateTransport(EndPoint endpoint) { try { return(GetOrAdd(endpoint, k => new Lazy <ITransport <TMessage> > (() => { var context = _bootstrap.StartConnectAsync(k).Result; var transportans = new DefaultTransport <TMessage> (context, _factory); return transportans; })).Value); } catch { RemoveTransport(endpoint, out var _); throw; } }
public async Task <ITransport <AmpMessage> > CreateTransport(EndPoint endpoint) { if (this.TRANSPORT_CACHE.TryGetValue(endpoint, out var transport)) { return(transport); } var context = await this._socket.ConnectAsync(endpoint); transport = new DefaultTransport(context); this.TRANSPORT_CACHE.AddOrUpdate(endpoint, transport, (k, old) => { //Dispose old.CloseAsync(CancellationToken.None).AnyContext(); return(transport); }); return(transport); }