diff --git a/src/csharp/Grpc.Core.Tests/ShutdownTest.cs b/src/csharp/Grpc.Core.Tests/ShutdownTest.cs
index a2be7ddd5e0d2feb776878f7869f747e544fe2d6..10d666d1098f8ed2d012dee0f998e4c5671c6495 100644
--- a/src/csharp/Grpc.Core.Tests/ShutdownTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ShutdownTest.cs
@@ -61,17 +61,20 @@ namespace Grpc.Core.Tests
         }
 
         [Test]
-        public async Task AbandonedCall()
+        public async Task AbandonedCall_ServerKillAsync()
         {
+            var readyToShutdown = new TaskCompletionSource<object>();
             helper.DuplexStreamingHandler = new DuplexStreamingServerMethod<string, string>(async (requestStream, responseStream, context) =>
             {
+                readyToShutdown.SetResult(null);
                 await requestStream.ToListAsync();
             });
 
-            var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall(new CallOptions(deadline: DateTime.UtcNow.AddMilliseconds(1))));
+            var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall());
+            await readyToShutdown.Task;  // make sure handler is running
 
-            channel.ShutdownAsync().Wait();
-            server.ShutdownAsync().Wait();
+            await channel.ShutdownAsync();  // channel.ShutdownAsync() works even if there's a pending call.
+            await server.KillAsync();  // server.ShutdownAsync() would hang waiting for the call to finish.
         }
     }
 }
diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs
index 0fadabe554c0911346302a691d7b27edeaa53c8e..d120f95fdf98e46db385378ccfa10ff117114929 100644
--- a/src/csharp/Grpc.Core/Server.cs
+++ b/src/csharp/Grpc.Core/Server.cs
@@ -171,6 +171,8 @@ namespace Grpc.Core
             handle.CancelAllCalls();
             await shutdownTcs.Task.ConfigureAwait(false);
             DisposeHandle();
+
+            await Task.Run(() => GrpcEnvironment.Release()).ConfigureAwait(false);
         }
 
         internal void AddCallReference(object call)