diff --git a/Directory.Build.props b/Directory.Build.props
index 0fb0ae78c..0434644c6 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -18,7 +18,7 @@
$(WarningsNotAsErrors);CS1591
true
- 8.0
+ 9.0
enable
diff --git a/src/Grpc.AspNetCore.Server.ClientFactory/ContextPropagationInterceptor.cs b/src/Grpc.AspNetCore.Server.ClientFactory/ContextPropagationInterceptor.cs
index becc177a6..891ac27b2 100644
--- a/src/Grpc.AspNetCore.Server.ClientFactory/ContextPropagationInterceptor.cs
+++ b/src/Grpc.AspNetCore.Server.ClientFactory/ContextPropagationInterceptor.cs
@@ -19,6 +19,7 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
+using System.Threading.Tasks;
using Grpc.AspNetCore.Server;
using Grpc.Core;
using Grpc.Core.Interceptors;
@@ -56,12 +57,13 @@ public override AsyncClientStreamingCall AsyncClientStreami
else
{
return new AsyncClientStreamingCall(
- call.RequestStream,
- call.ResponseAsync,
- call.ResponseHeadersAsync,
- call.GetStatus,
- call.GetTrailers,
- () => { call.Dispose(); cts.Dispose(); });
+ requestStream: call.RequestStream,
+ responseAsync: call.ResponseAsync,
+ responseHeadersAsync: ClientStreamingCallbacks.GetResponseHeadersAsync,
+ getStatusFunc: ClientStreamingCallbacks.GetStatus,
+ getTrailersFunc: ClientStreamingCallbacks.GetTrailers,
+ disposeAction: ClientStreamingCallbacks.Dispose,
+ CreateContextState(call, cts));
}
}
@@ -75,12 +77,13 @@ public override AsyncDuplexStreamingCall AsyncDuplexStreami
else
{
return new AsyncDuplexStreamingCall(
- call.RequestStream,
- call.ResponseStream,
- call.ResponseHeadersAsync,
- call.GetStatus,
- call.GetTrailers,
- () => { call.Dispose(); cts.Dispose(); });
+ requestStream: call.RequestStream,
+ responseStream: call.ResponseStream,
+ responseHeadersAsync: DuplexStreamingCallbacks.GetResponseHeadersAsync,
+ getStatusFunc: DuplexStreamingCallbacks.GetStatus,
+ getTrailersFunc: DuplexStreamingCallbacks.GetTrailers,
+ disposeAction: DuplexStreamingCallbacks.Dispose,
+ CreateContextState(call, cts));
}
}
@@ -94,11 +97,12 @@ public override AsyncServerStreamingCall AsyncServerStreamingCall(
- call.ResponseStream,
- call.ResponseHeadersAsync,
- call.GetStatus,
- call.GetTrailers,
- () => { call.Dispose(); cts.Dispose(); });
+ responseStream: call.ResponseStream,
+ responseHeadersAsync: ServerStreamingCallbacks.GetResponseHeadersAsync,
+ getStatusFunc: ServerStreamingCallbacks.GetStatus,
+ getTrailersFunc: ServerStreamingCallbacks.GetTrailers,
+ disposeAction: ServerStreamingCallbacks.Dispose,
+ CreateContextState(call, cts));
}
}
@@ -112,11 +116,12 @@ public override AsyncUnaryCall AsyncUnaryCall(TR
else
{
return new AsyncUnaryCall(
- call.ResponseAsync,
- call.ResponseHeadersAsync,
- call.GetStatus,
- call.GetTrailers,
- () => { call.Dispose(); cts.Dispose(); });
+ responseAsync: call.ResponseAsync,
+ responseHeadersAsync: UnaryCallbacks.GetResponseHeadersAsync,
+ getStatusFunc: UnaryCallbacks.GetStatus,
+ getTrailersFunc: UnaryCallbacks.GetTrailers,
+ disposeAction: UnaryCallbacks.Dispose,
+ CreateContextState(call, cts));
}
}
@@ -192,6 +197,27 @@ private bool TryGetServerCallContext([NotNullWhen(true)]out ServerCallContext? s
return true;
}
+ private ContextState CreateContextState(TCall call, CancellationTokenSource cancellationTokenSource) where TCall : IDisposable =>
+ new ContextState(call, cancellationTokenSource);
+
+ private class ContextState : IDisposable where TCall : IDisposable
+ {
+ public ContextState(TCall call, CancellationTokenSource cancellationTokenSource)
+ {
+ Call = call;
+ CancellationTokenSource = cancellationTokenSource;
+ }
+
+ public TCall Call { get; }
+ public CancellationTokenSource CancellationTokenSource { get; }
+
+ public void Dispose()
+ {
+ Call.Dispose();
+ CancellationTokenSource.Dispose();
+ }
+ }
+
private static class Log
{
private static readonly Action _propagateServerCallContextFailure =
@@ -202,5 +228,44 @@ public static void PropagateServerCallContextFailure(ILogger logger, string erro
_propagateServerCallContextFailure(logger, errorMessage, null);
}
}
+
+ // Store static callbacks so delegates are allocated once
+ private static class UnaryCallbacks
+ where TResponse : class
+ {
+ internal static readonly Func