diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs index e7b30cd1e94..d4fcd1ad9c2 100644 --- a/src/csharp/Grpc.Core/Channel.cs +++ b/src/csharp/Grpc.Core/Channel.cs @@ -160,8 +160,18 @@ namespace Grpc.Core var deadlineTimespec = deadline.HasValue ? Timespec.FromDateTime(deadline.Value) : Timespec.InfFuture; lock (myLock) { - // pass "tcs" as "state" for WatchConnectivityStateHandler. - handle.WatchConnectivityState(lastObservedState, deadlineTimespec, completionQueue, WatchConnectivityStateHandler, tcs); + if (handle.IsClosed) + { + // If channel has been already shutdown and handle was disposed, we would end up with + // an abandoned completion added to the completion registry. So we act as if the + // wait has timed out instead. + tcs.SetResult(false); + } + else + { + // pass "tcs" as "state" for WatchConnectivityStateHandler. + handle.WatchConnectivityState(lastObservedState, deadlineTimespec, completionQueue, WatchConnectivityStateHandler, tcs); + } } return tcs.Task; }