C# 我需要一个更好的方法来使用GetAwaiter().OnCompleted进行Grpc AsyncUnaryCall

C# 我需要一个更好的方法来使用GetAwaiter().OnCompleted进行Grpc AsyncUnaryCall,c#,async-await,grpc,C#,Async Await,Grpc,我尝试从grpc服务调用读取响应头/元数据。为了在一个中心点实现这一点,我使用了一个自定义调用调用程序,它封装了真正的底层HttpClientInvoker 到目前为止,我的呼叫代码非常简单,只需呼叫3次 var greeter = new GreeterClient(new MyCustomCallInvoker()); await greeter.SayHelloAsync(new HelloRequest { Name = nameof(TestSayHello) }); await gr

我尝试从grpc服务调用读取响应头/元数据。为了在一个中心点实现这一点,我使用了一个自定义调用调用程序,它封装了真正的底层
HttpClientInvoker

到目前为止,我的呼叫代码非常简单,只需呼叫3次

var greeter = new GreeterClient(new MyCustomCallInvoker());
await greeter.SayHelloAsync(new HelloRequest { Name = nameof(TestSayHello) });
await greeter.SayHelloAsync(new HelloRequest { Name = nameof(TestSayHello) });
await greeter.SayHelloAsync(new HelloRequest { Name = nameof(TestSayHello) });
自定义调用程序执行如下操作

public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(
                                    Method<TRequest, TResponse> method,
                                    string host,
                                    CallOptions options,
                                    TRequest request)
{
   var result = Invoker.AsyncUnaryCall<TRequest, TResponse>(method, host, options, request);
   Action updateMetadata = delegate
   {
      var trailers = result.GetTrailers();
      UpdateMetadata(trailers);
   };
   result.GetAwaiter().OnCompleted(updateMetadata);
   return result;
}
public重写AsyncUnaryCall AsyncUnaryCall(
方法,,
字符串主机,
CallOptions选项,
TRequest请求)
{
var result=Invoker.AsyncUnaryCall(方法、主机、选项、请求);
Action updateMetadata=委托
{
var=result.GetTrailers();
更新数据(拖车);
};
result.GetAwaiter().OnCompleted(updateMetadata);
返回结果;
}
我知道使用
GetAwaiter()
不是很好。不幸的是,调用程序在这里不使用
任务
,并且
异步调用
是密封的

然而,在第一次更新预告片之前,对迎宾员的呼叫通过了2次

我没有看到一种方法可以在调用程序
Invoker.AsyncUnaryCall
通过之后,以及在返回调用代码之前立即更新本地预告片,而不会阻塞进程。(编辑:如果我只是在OnCompleted中放置一个Console.Write(“完成”),它会按预期工作。)


这在某种程度上是可能的?

花了一些时间,但我找到了一个解决方案,我想与社区分享。 这里的问题是AsyncUnaryCall(花费TaskWaiter) 是密封的

我查看了一下grpc源代码,发现AsyncUnaryCall只是一个包含大量回调的容器。这两个原型如下所示:

public AsyncUnaryCall(Task<TResponse> responseAsync, Task<Metadata> responseHeadersAsync, Func<Status> getStatusFunc, Func<Metadata> getTrailersFunc, Action disposeAction);

public AsyncUnaryCall(Task<TResponse> responseAsync, Func<object, Task<Metadata>> responseHeadersAsync, Func<object, Status> getStatusFunc, Func<object, Metadata> getTrailersFunc, Action<object> disposeAction, object state)
public AsyncUnaryCall(任务响应同步、任务响应头异步、Func getStatusFunc、Func getTrailersFunc、动作处理);
public AsyncUnaryCall(任务响应同步、Func ResponseHeaderAsync、Func getStatusFunc、Func GetTrailerFunc、动作处理、对象状态)
这就是我的问题的解决方案,创建第二个AsyncUnaryCall作为代理,它封装了原始AsyncUnaryCall,并通过在ResponseAsync回调中添加getTrailer稍微修改它们


希望这对将来的人有所帮助。

@yogihosting这与我的问题无关。我猜这只是你网站的seo链接。我猜你的意思是
CallInvoker/DefaultCallInvoker
不是
HttpClientInvoker
?还有,
OnCompleted
从何而来?@IanKemp我想是这样:@ChrisYungmann啊,我在gRPC中期待着一些东西。。。不是标记为“此API支持产品基础结构,不打算直接从代码中使用”的附带方法。IDisposable,考虑到文档,您可能不应该使用该方法。抱歉,您是对的@IDisposable由于您提到的问题,我发布的答案将不起作用。也许这会有所帮助?看起来您应该返回一个新的
AsyncUnaryCall
实例,然后您可以提供任何异步逻辑。