/// <summary> /// Gets the list of <see cref="IpcEndpointInfo"/> served from the reversed diagnostics server. /// </summary> /// <param name="token">The token to monitor for cancellation requests.</param> /// <returns>A list of active <see cref="IEndpointInfo"/> instances.</returns> public async Task <IEnumerable <IEndpointInfo> > GetEndpointInfoAsync(CancellationToken token) { VerifyNotDisposed(); VerifyIsListening(); using CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(token, _cancellation.Token); CancellationToken linkedToken = linkedSource.Token; // Prune connections that no longer have an active runtime instance before // returning the list of connections. await _endpointInfosSemaphore.WaitAsync(linkedToken).ConfigureAwait(false); try { // Check the transport for each endpoint info and remove it if the check fails. IDictionary <EndpointInfo, Task <bool> > checkMap = new Dictionary <EndpointInfo, Task <bool> >(); foreach (EndpointInfo info in _endpointInfos) { checkMap.Add(info, Task.Run(() => CheckNotViable(info, linkedToken), linkedToken)); } // Wait for all checks to complete await Task.WhenAll(checkMap.Values).ConfigureAwait(false); // Remove connections for failed checks foreach (KeyValuePair <EndpointInfo, Task <bool> > entry in checkMap) { if (entry.Value.Result) { _endpointInfos.Remove(entry.Key); OnRemovedEndpointInfo(entry.Key); _server?.RemoveConnection(entry.Key.RuntimeInstanceCookie); } } return(_endpointInfos.ToList()); } finally { _endpointInfosSemaphore.Release(); } }
private async Task PruneIfNotViable(EndpointInfo info, CancellationToken token) { using var timeoutSource = new CancellationTokenSource(); using var linkedSource = CancellationTokenSource.CreateLinkedTokenSource(token, timeoutSource.Token); try { timeoutSource.CancelAfter(PruneWaitForConnectionTimeout); await info.Endpoint.WaitForConnectionAsync(linkedSource.Token).ConfigureAwait(false); } catch { // Only remove the endpoint info if due to some exception // other than cancelling the pruning operation. if (!token.IsCancellationRequested) { _endpointInfos.Remove(info); OnRemovedEndpointInfo(info); _server?.RemoveConnection(info.RuntimeInstanceCookie); } } }