skip to Main Content

(This question text reflects an invalid assumption: I assumed that it was possible to call a grpc-net remote method synchronously. It’s not, except in a superficial sense. See the answer that I posted.)

I have a large ASP.NET MVC app running on .NET 4.8 that does not have any async methods. It calls methods on grpc-net server. The methods are not async, because at this time I cannot refactor the ASP.NET MVC app to use async throughout.

It seems a shame that this lack of async on the client side is pushed into my grpc server. Theoretically, it seems that these server side methods ought to be able to use async, because, after all, this thread pool has nothing to do with the client’s thread pool. But I don’t see a way to make this happen. I can’t define the methods as async because then on the client side I’d need to either 1) use async/yield throughout the application call stack, which I can’t do at this time or 2) use task.Result, which has the deadlock risk in ASP.NET MVC.

Oh, and AFAICT, I can’t use ConfigureAwait(false) either, because, you know, ASP.NET.

Is there any other solution? In sum, I think that a solution would result in legacy blocked-thread semantics on the client side but async / await semantics on the server side.

2

Answers


  1. Chosen as BEST ANSWER

    The answer is No: it is essentially not possible to call a remote method synchronously, using the grpc-net client. That's because grpc-net always executes the calls asynchronously.

    When the remote method is a non-async method, the grpc client will do a blocking wait for the result, thus giving the appearance of a synchronous operation. relevant grpc source

    This will cause deadlock when the client application is ASP.NET (non-core), or a Windows UI application, which uses a single thread for UI operations. The issue is described here

    So, lesson learned: you must not call non-async remote methods in these environments. Or if you do, you must call them on a background ThreadPool thread, typically by using Task.Run( () => myRemoteMethod(parms)) and accessing the result. The performance impact of that approach depends on the application. You should strive to avoid this sync-over-async approach.


  2. Client and server are separated by HTTP.

    There’s no other constraints one imposes to the other.

    They don’t need to even be coded in the same programming language, use the same frameworks or even run in the same operating system.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search