I'm trying to use server streaming using GRPC with C#, and my client receives one response and then throws error:
Shutdown has already been called
at Grpc.Core.Internal.CompletionQueueSafeHandle.BeginOp()
at Grpc.Core.Internal.CallSafeHandle.StartReceiveMessage(IReceivedMessageCallback callback)
at Grpc.Core.Internal.AsyncCallBase`2.ReadMessageInternalAsync()
at Grpc.Core.Internal.ClientResponseStream`2.<MoveNext>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at GRPCTransferClient.Program.<Test>d__1.MoveNext() in Program.cs:line 25
I tried throttling the responses by putting delays both on the server and client side but I still got the error. But I noticed that if I put a 1 second delay on the client before trying to call MoveNext() I won't even get the first response and it throws the error immediately.
My proto is this:
syntax = "proto3";
package Mega.SplitText;
service SplitText {
rpc Split(Text) returns (stream Line) {}
}
message Text {
string text = 1;
}
message Line {
string line = 1;
}
Server code:
public class SplitTextServiceImpl : SplitTextBase
{
public SplitTextServiceImpl()
{
}
public override async Task Split(Text request, IServerStreamWriter<Line> responseStream, ServerCallContext context)
{
foreach (string line in request.Text_.Split(';'))
{
await responseStream.WriteAsync(new Line { Line_ = line });
Console.WriteLine($"Sent {line}");
}
}
}
Client code:
class Program
{
static void Main(string[] args)
{
var program = new Program();
program.Test();
}
async void Test()
{
Channel channel = new Channel($"127.0.0.1:50051", ChannelCredentials.Insecure);
var client = new SplitTextClient(channel);
using (var response = client.Split(new Text { Text_ = "a;b;c;d;e" }))
{
while (await response.ResponseStream.MoveNext())
{
Console.WriteLine(response.ResponseStream.Current);
}
}
Console.ReadLine();
}
}
I copied this structure from the examples folder on the official GRPC repository, and that works fine on my machine, so I have no idea what I'm doing wrong in this other project.
The projects are both .Net Core 2.0, but I also tried with .Net Framework 4.6.1 just in case. In both cases the result is the same.