我尝试使用带有C#的GRPC使用服务器流,我的客户端收到一个响应,然后抛出错误:
已经调用了关机
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
我尝试通过在服务器端和客户端都放置延迟来限制响应,但我仍然遇到错误。但是我注意到如果我在尝试调用MoveNext()之前在客户端上放置了1秒钟的延迟,我甚至不会得到第一个响应并立即抛出错误。
我的原型是:
syntax = "proto3";
package Mega.SplitText;
service SplitText {
rpc Split(Text) returns (stream Line) {}
}
message Text {
string text = 1;
}
message Line {
string line = 1;
}
服务器代码:
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}");
}
}
}
客户代码:
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();
}
}
我从官方GRPC存储库的examples文件夹中复制了这个结构,这在我的机器上工作正常,所以我不知道我在这个其他项目中做错了什么。
这些项目都是.Net Core 2.0,但我也试过.Net Framework 4.6.1以防万一。在这两种情况下,结果都是一样的。
答案 0 :(得分:1)
解决了,问题是我忘了等待客户端异步功能。解决方案:
static void Main(string[] args)
{
var program = new Program();
program.Test().Wait(); // Need to wait here
}
async Task 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" }))
{
await Task.Delay(1000);
while (await response.ResponseStream.MoveNext())
{
Console.WriteLine(response.ResponseStream.Current);
}
}
Console.ReadLine();
}