从服务器返回的 gRPC 元数据仅在 C# 客户端使用异步调用时可用?

gRPC metada returned from server only available when C# client uses async calls?

我正在尝试将 gRPC 作为一种可能使用的技术。我用 C++ 编写了一个同步客户端和服务器。服务器returns元数据给客户端,客户端可以成功访问元数据。

我现在正在用相同的 C++ 同步服务器测试 C# 客户端。似乎要访问服务器返回的元数据,客户端必须使用对服务器的异步调用。我无法让它工作,所以我想知道:

  1. 它应该有效吗?
  2. 有没有办法在不使用客户端调用的异步版本的情况下获取元数据?

由于我的测试无法正常工作,任何人都可以发现我做错了什么。我有一个看起来像下面代码的方法。当客户端调用 'Connect' 方法时,我希望服务器生成一个唯一的密钥并将其发回。从那时起,客户端在元数据中发送该密钥,以便服务器可以确定哪个客户端正在调用。

这是我的尝试。传递给方法的"ItemInterface.Items.ItemsClient client"参数是protoc:

生成的class的一个实例
private static async Task<string> _MakeConnection(ItemInterface.Items.ItemsClient client, ItemInterface.ConnectRequest request)
{
    string serverAssignedKey = "";
    CallOptions options = new CallOptions();

    var answer = client.ConnectAsync(request, options);
    var response = await answer.ResponseAsync;
    serverAssignedKey = answer.GetTrailers().First(e => e.Key == "client_id").Value;

    return serverAssignedKey;
}

调用到达服务器并离开服务器,但之后再也不会 returns 回到我的调用方法。客户端挂了。

谢谢。

I'm now testing a c# client with the same c++ synchronous server. It appears that to get access to metadata returned by the server, the client must use an async call to the server.

在处理任何一种网络通信(包括gRPC)时,服务端的同步和异步完全独立于客户端的同步和异步。服务器同步的事实对客户端没有任何影响;无论服务器实现如何,它都可以是同步的或异步的。

The call makes it to the server and leaves the server, but then never returns back to my calling method. The client is hung.

这是提供线索的部分:当异步调用挂起时,很可能是由于 deadlock,因为该代码已在调用堆栈更上层的某个地方被阻塞。更具体地说,C# 中的 await 默认捕获 "context"。一种常见的情况是 GUI 应用程序,它有一个 UI 上下文,它只在 UI 线程上运行。如果代码通过等待此任务完成来阻塞 UI 线程,那么当 await 准备好恢复该方法时,它不能因为 UI 线程被阻塞。

最好的解决方案是不阻塞异步代码 - 即使用 "async all the way". There are alternatives,但它们的风险要大得多。