如何解决我需要一个更好的主意,因为使用GetAwaiterOnCompleted用于Grpc AsyncUnaryCall
我尝试从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;
}
我知道使用GetAwaiter()
不太好。不幸的是,调用者在这里没有使用Task
并且AsyncUnaryCall
是密封的。
但是,在第一次更新预告片之前,打了招呼的电话就响了2次。
在Invoker.AsyncUnaryCall
通过之后,并且在返回调用代码之前,我没有看到一种方法来更新本地预告片,而又不会阻塞该过程。 (编辑:如果我只是将Console.Write(“ done”)放在OnCompleted中,它将按预期工作。)
有可能吗?
解决方法
花了一段时间,但是我找到了一个我想与社区分享的解决方案。 这里的问题是AsyncUnaryCall(花了TaskAwaiter) 是密封的。
我看了看grpc的源代码,看到AsyncUnaryCall只是一堆回调的容器。 ctor原型如下所示:
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,Status> getStatusFunc,Metadata> getTrailersFunc,Action<object> disposeAction,object state)
这是解决我的问题的方法,它创建了第二个AsyncUnaryCall作为代理,将原始AsyncUnaryCall封装起来,并通过在ResponseAsync回调中添加GetTrailers对其进行了一些修改。
希望这对以后的人有帮助。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。