1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C# gRPC RpcException をスローしたときにメソッド呼び出しが終わらなくなる

Posted at

サービス側の処理で RpcException をスローすることがありますが、クライアント側から呼び出したメソッドが終了しないケースを発見しました。一見何の問題もないように見えてしまうため、注意が必要です。

gRPC のバージョンは 1.16.0 ですが、他のバージョンでも発生するかもしれません。

サービスの実装

RpcException のトレーラーに格納する内容をいったん ServerCallContext に格納し、ServerCallContext の ResponseTrailers プロパティ経由で RpcException に格納します。

RpcExceptionをスローするサービスメソッド(1)
public override Task<Response> GetData(Request request, ServerCallContext context)
{
    // ServerCallContext にトレーラーを格納し、
    context.ResponseTrailers.Add("result", "1");

    // ServerCallContext からトレーラーを取得して例外に格納する。
    throw new RpcException(
        new Status(StatusCode.Unauthenticated, "Unauthenticated.")
        , context.ResponseTrailers
    );
}

ちなみに ServerCallContext.ResponseTrailers を使わなければこの現象は発生しません。通常はこちらのように実装すると思います。

RpcExceptionをスローするサービスメソッド(2)
public override Task<Response> GetData(Request request, ServerCallContext context)
{
    // Metadata にトレーラーを格納し、
    Metadata trailers = new Metadata();
    trailers.Add("result", "1");

    // Metadata を例外に格納する。
    throw new RpcException(
        new Status(StatusCode.Unauthenticated, "Unauthenticated.")
        , trailers
    );
}

クライアントの実装

メソッドの呼び出しが終わらず、ブロックされたままになります。

上記のサービスメソッド(1)を呼び出す
try
{
    // このメソッド呼び出しが終わらない。
    Response response = await rpcClient.GetData(new Request());
}
catch (Exception ex)
{
    // 切断されたりするまで例外はキャッチされない。
    Debug.WriteLine(ex.ToString());
}
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?