Merge pull request #21667 from jtattermusch/csharp_channelbase_shutdownasync

Introduce ChannelBase.ShutdownAsync() in a backward-compatible manner.
reviewable/pr21335/r8
Jan Tattermusch 5 years ago committed by GitHub
commit 7faa779504
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 30
      src/csharp/Grpc.Core.Api/ChannelBase.cs
  2. 10
      src/csharp/Grpc.Core.Tests/ChannelTest.cs
  3. 14
      src/csharp/Grpc.Core/Channel.cs

@ -17,6 +17,7 @@
#endregion #endregion
using System; using System;
using System.Threading.Tasks;
using Grpc.Core.Utils; using Grpc.Core.Utils;
namespace Grpc.Core namespace Grpc.Core
@ -48,5 +49,34 @@ namespace Grpc.Core
/// </summary> /// </summary>
/// <returns>A new <see cref="CallInvoker"/>.</returns> /// <returns>A new <see cref="CallInvoker"/>.</returns>
public abstract CallInvoker CreateCallInvoker(); public abstract CallInvoker CreateCallInvoker();
/// <summary>
/// Shuts down the channel cleanly. It is strongly recommended to shutdown
/// the channel once you stopped using it.
/// </summary>
/// <remarks>
/// Guidance for implementors:
/// This method doesn't wait for all calls on this channel to finish (nor does
/// it have to explicitly cancel all outstanding calls). It is user's responsibility to make sure
/// all the calls on this channel have finished (successfully or with an error)
/// before shutting down the channel to ensure channel shutdown won't impact
/// the outcome of those remote calls.
/// </remarks>
public Task ShutdownAsync()
{
return ShutdownAsyncCore();
}
/// <summary>Provides implementation of a non-virtual public member.</summary>
#pragma warning disable 1998
protected virtual async Task ShutdownAsyncCore()
{
// default implementation is no-op for backwards compatibility, but all implementations
// are expected to override this method.
// warning 1998 is disabled to avoid needing TaskUtils.CompletedTask, which is
// only available in Grpc.Core
}
#pragma warning restore 1998
} }
} }

@ -113,5 +113,15 @@ namespace Grpc.Core.Tests
Assert.Throws(typeof(ObjectDisposedException), () => { var x = channel.ResolvedTarget; }); Assert.Throws(typeof(ObjectDisposedException), () => { var x = channel.ResolvedTarget; });
Assert.ThrowsAsync(typeof(TaskCanceledException), async () => await channel.ConnectAsync()); Assert.ThrowsAsync(typeof(TaskCanceledException), async () => await channel.ConnectAsync());
} }
[Test]
public async Task ChannelBaseShutdownAsyncInvokesShutdownAsync()
{
var channel = new Channel("localhost", ChannelCredentials.Insecure);
ChannelBase channelBase = channel;
await channelBase.ShutdownAsync();
// check that Channel.ShutdownAsync has run
Assert.AreEqual(ChannelState.Shutdown, channel.State);
}
} }
} }

@ -210,18 +210,8 @@ namespace Grpc.Core
} }
} }
/// <summary> /// <summary>Provides implementation of a non-virtual public member.</summary>
/// Shuts down the channel cleanly. It is strongly recommended to shutdown protected override async Task ShutdownAsyncCore()
/// all previously created channels before exiting from the process.
/// </summary>
/// <remarks>
/// This method doesn't wait for all calls on this channel to finish (nor does
/// it explicitly cancel all outstanding calls). It is user's responsibility to make sure
/// all the calls on this channel have finished (successfully or with an error)
/// before shutting down the channel to ensure channel shutdown won't impact
/// the outcome of those remote calls.
/// </remarks>
public async Task ShutdownAsync()
{ {
lock (myLock) lock (myLock)
{ {

Loading…
Cancel
Save