static Task CloseCommunicationObjectAsync(object obj, bool aborted, CancellationToken token) { if (obj != null) { ICommunicationObject co = obj as ICommunicationObject; if (co != null) { if (aborted) { try { co.Abort(); } catch (CommunicationException e) { DiagnosticUtility.TraceHandledException(e, TraceEventType.Information); } } else { return(co.CloseAsync(token)); } } else if (obj is IDisposable) { ((IDisposable)obj).Dispose(); } } return(Task.CompletedTask); }
/// <summary> /// Safely disposes the channel by either closing or aborting it. /// </summary> /// <param name="communicationObject">The channel to dispose.</param> /// <param name="logger">A logger to be used for logging purposes.</param> /// <exception cref="ArgumentNullException">The <paramref name="communicationObject"/> is null.</exception> public static async Task DisposeChannelAsync(this ICommunicationObject communicationObject, ILogger?logger = null) { _ = communicationObject ?? throw new ArgumentNullException(nameof(communicationObject)); logger ??= NullLogger.Instance; try { switch (communicationObject.State) { case CommunicationState.Opened: logger.LogDebug("Closing connection"); await communicationObject.CloseAsync().ConfigureAwait(false); break; case CommunicationState.Faulted: logger.LogDebug("Aborting connection"); communicationObject.Abort(); break; case CommunicationState.Closed: case CommunicationState.Closing: case CommunicationState.Created: case CommunicationState.Opening: break; default: throw new InvalidOperationException($"The channel is in an unexpected state: {communicationObject.State:G}"); } } catch (CommunicationException ex) { logger.LogError(ex, "An error occurred while closing the connection"); communicationObject.Abort(); } catch (TimeoutException ex) { logger.LogError(ex, "An error occurred while closing the connection"); communicationObject.Abort(); } catch (Exception ex) { logger.LogError(ex, "An error occurred while closing the connection"); communicationObject.Abort(); throw; } }