// Calls neighbor.BeginClose or EndClose and catches appropriate exceptions for any cleanup. // We use a single method for both BeginClose and EndClose processing since exception handling // is very similar in both cases. void InvokeAsyncNeighborClose(PeerNeighbor neighbor, PeerCloseReason closeReason, PeerCloseInitiator closeInitiator, Exception closeException, IAsyncResult endResult) { // initiate invoking BeginClose or EndClose try { if (endResult == null) { IAsyncResult beginResult = neighbor.BeginClose(closeReason, closeInitiator, closeException, Fx.ThunkCallback(new AsyncCallback(OnNeighborClosedCallback)), neighbor); if (beginResult.CompletedSynchronously) neighbor.EndClose(beginResult); } else { neighbor.EndClose(endResult); } } catch (Exception e) { if (Fx.IsFatal(e)) throw; DiagnosticUtility.TraceHandledException(e, TraceEventType.Information); neighbor.TraceEventHelper(TraceEventType.Warning, TraceCode.PeerNeighborCloseFailed, SR.GetString(SR.TraceCodePeerNeighborCloseFailed), e); // May get InvalidOperationException or ObjectDisposedException due to simultaneous close from both sides (and autoclose is enabled) if (e is InvalidOperationException || e is CommunicationException || e is TimeoutException) { neighbor.Abort(); } else { throw; } } }