异步/等待不等待任务完成

时间:2020-10-12 07:30:39

标签: c# .net-core grpc

我正在尝试使用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;
    }
}

更多信息:

  1. .net-core 3.1用于表单和Web服务。
  2. 客户端正在通过grpc.net.client连接到服务

谢谢

编辑

我知道通信是可行的,因为如果我执行类似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});
        }
    }
}

}

1 个答案:

答案 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,这就是为什么它不等待答案。将其更改为引用具有返回类型的方法即可解决此问题。