我正在尝试使用gRPC设置双向流。我已经阅读了他们的教程,并阅读了有关Stack Overflow的其他解决方案,但是这些似乎都无法解决我的问题。
出于测试目的,我创建了一个简单的按钮单击事件,旨在如下所述将其全部消除。在我等待所有呼叫的同时,message
在等待resultTask
完成之前被处理。据我了解,await
运算符应坐在resultTask
完成之前,先完成操作。
有人可以协助概述我在这里做错了什么吗?
private async void B_Click(object sender, EventArgs e)
{
try
{
await CallServer();
}
catch (Exception exception)
{
_box.Text = exception.Message;
}
}
private static async Task CallServer()
{
Greeter.GreeterClient client = new Greeter.GreeterClient(GrpcChannel.ForAddress("https://localhost:5001"));
using var message = client.Echos();
var resultTask = Task.Run(action: (async () =>
{
while (await message.ResponseStream.MoveNext(CancellationToken.None))
{
//Write out the result of the response
}
}));
List<HelloRequest> hellos = new List<HelloRequest>();
for (int i = 0; i < 10; i++)
{
hellos.Add(new HelloRequest() { Name = i.ToString() });
}
foreach (var hello in hellos)
{
await message.RequestStream.WriteAsync(hello);
}
await message.RequestStream.CompleteAsync();
await resultTask;
}
}
更多信息:
谢谢
编辑
我知道通信是可行的,因为如果我执行类似Console.ReadKey()的操作,或者将using var message = client.Echos()
替换为var message = client.Echos()
,则消息将返回正常(但仍不等待)。 / p>
也就是说,这是原型:
syntax =“ proto3”; 选项csharp_namespace =“ GrpcService1”;
包裹打招呼;
服务问候者{ rpc Echos(流HelloRequest)返回(流.greet.HelloReply); }
消息HelloRequest { 字符串名称= 1; }
消息HelloReply { 字符串消息= 1; }
和服务器代码:
public class GreeterService : Greeter.GreeterBase
{
private readonly ILogger<GreeterService> _logger;
public GreeterService(ILogger<GreeterService> logger)
{
_logger = logger;
}
public override async Task Echos(IAsyncStreamReader<HelloRequest> requestStream, IServerStreamWriter<HelloReply> responseStream, ServerCallContext context)
{
while (await requestStream.MoveNext())
{
await responseStream.WriteAsync(new HelloReply() {Message = "Hello " + requestStream.Current.Name});
}
}
}
}
答案 0 :(得分:0)
感谢您的反馈,我设法通过重构未完成等待的方法来解决此问题。我删除了Task.Run
并将其替换为一个返回值的async
方法:
private async Task CallServer()
{
Greeter.GreeterClient client = new Greeter.GreeterClient(GrpcChannel.ForAddress("https://localhost:5001"));
using var message = client.Echos();
var resultTask = CompletedTask(message);
List<HelloRequest> hellos = new List<HelloRequest>();
for (int i = 0; i < 10; i++)
{
hellos.Add(new HelloRequest() { Name = i.ToString() });
}
foreach (var hello in hellos)
{
await message.RequestStream.WriteAsync(hello);
}
await message.RequestStream.CompleteAsync();
var x = await resultTask;
_box.Text += "Done!";
}
private async Task<bool> CompletedTask(AsyncDuplexStreamingCall<HelloRequest, HelloReply> message)
{
await foreach (var result in message.ResponseStream.ReadAllAsync())
{
_box.Text += result.Message + @"\r\n";
}
return true;
}
Task.Run
返回的方法签名的返回类型为void
,这就是为什么它不等待答案。将其更改为引用具有返回类型的方法即可解决此问题。