Метаданные gRP C, возвращаемые с сервера, доступны только в том случае, если клиент C# использует асинхронные вызовы c? - PullRequest
1 голос
/ 21 февраля 2020

Я экспериментирую с gRP C в качестве возможной технологии для использования. Я написал синхронный клиент и сервер на C ++. Сервер возвращает метаданные клиенту, и клиент может успешно получить доступ к метаданным.

Сейчас я тестирую c# клиента с тем же синхронным сервером c ++. Похоже, что для получения доступа к метаданным, возвращаемым сервером, клиент должен использовать asyn c вызов сервера. Я не могу заставить это работать, поэтому мне интересно:

  1. Должно ли это работать?
  2. Есть ли способ получить метаду без использования asyn c версии звонки от клиента?

Так как мой тест не может заставить это работать, кто-нибудь может заметить, что я делаю неправильно. У меня есть метод, который выглядит как код ниже. Когда клиент вызывает метод Connect, я хочу, чтобы сервер сгенерировал уникальный ключ и отправил его обратно. С этого момента клиент отправляет этот ключ в метаданных, чтобы сервер мог определить, какой клиент вызывает.

Вот моя попытка. Параметр «ItemInterface.Items.ItemsClient client», переданный методу, является экземпляром класса, созданного proto c:

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;
}

Вызов поступает на сервер и покидает сервер, но затем никогда не возвращается к моему вызывающему методу. Клиент завис.

Спасибо.

1 Ответ

2 голосов
/ 22 февраля 2020

Сейчас я тестирую c# клиента с тем же синхронным сервером c ++. Похоже, что для получения доступа к метаданным, возвращаемым сервером, клиент должен использовать асин c вызов сервера.

При работе с любым видом сетевого взаимодействия (включая gRP C). ), синхронность и асинхронность сервера полностью независимы от синхронности и асинхронности клиента. Тот факт, что сервер является синхронным, не влияет на клиента; он может быть синхронным или асинхронным независимо от реализации сервера.

Вызов поступает на сервер и покидает сервер, но затем никогда не возвращается к моему вызывающему методу. Клиент зависает.

Вот часть, которая дает ключ: когда асинхронный вызов зависает, это, скорее всего, из-за взаимоблокировки , потому что этот код где-то заблокирован дальше вверх по стеку вызовов. Более конкретно, await в C# по умолчанию захватывает «контекст». Одним из распространенных сценариев является GUI приложения, которые имеют контекст пользовательского интерфейса, который выполняется только в потоке пользовательского интерфейса. Если код блокирует поток пользовательского интерфейса, ожидая завершения этой задачи, то, когда await готов возобновить метод, он не может этого сделать, поскольку поток пользовательского интерфейса заблокирован.

Лучшее решение состоит в том, чтобы не блокировать асинхронный код - т. е. использовать "asyn c полностью" . Есть альтернатив , но они намного более рискованны.

...