我在grpc-dotnet 3.1中为一个项目工作。在服务器端,grpc调用将执行本地系统进程(例如二进制文件或脚本)。我遇到的问题是通过grpc客户端将来自进程的重定向输出进行流式处理。我现在得到的只是第一行输出。这是我的测试代码。
public override async Task ExecuteProcess(ProcessRequest request, IServerStreamWriter<ProcessReply> responseStream, ServerCallContext context)
{
_logger.LogInformation($"Received Execution request for {request.Name}");
_logger.LogInformation($"Received Args {request.Args}");
using (var process = new Process())
{
process.StartInfo.FileName = @"cmd.exe";
process.StartInfo.Arguments = @"/c dir"; // print the current working directory information
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
//process.OutputDataReceived += async(sender, e) => await responseStream.WriteAsync(new ProcessReply { Message = e.Data });
process.OutputDataReceived += (sender, e) => ShowOutput(e.Data, responseStream)
process.Start();
process.BeginOutputReadLine();
//process.BeginErrorReadLine();
var exited = process.WaitForExit(1000 * 10); // (optional) wait up to 10 second
}
//return Task.FromResult(new ProcessReply { Message = "Executed " + request.Name });
await responseStream.WriteAsync(new ProcessReply
{
Message = "Process Complete"
});
}
private async Task ShowOutput(string data, IServerStreamWriter<ProcessReply> responseStream)
{
if (data != null)
{
_logger.LogInformation($"Process Output {data}");
await responseStream.WriteAsync(new ProcessReply { Message = data });
}
}在客户端,我只是使用流服务器示例代码来读取流中的行。
await foreach (var message in call.ResponseStream.ReadAllAsync())
{
Console.WriteLine("Server Out: " + message.Message);
}你知道为什么我只能从重定向的进程输出中得到一行进程输出吗?我也只看到了记录器输出中的一行。
发布于 2020-06-09 00:34:31
这可能是因为您正在从事件处理程序写入ResponseStream,该事件处理程序不一定会在流的正确异步上下文中被调用。
看看CliWrap,它将整个流程执行过程包装在一个非常好的应用程序接口中,其中包括一个ListenAsync方法,它返回一个IAsyncEnumerable,您可以对其进行await foreach覆盖,并将输出写入流。
借用README,它看起来像这样:
var cmd = Cli.Wrap("cmd.exe").WithArguments("/c dir");
await foreach (var cmdEvent in cmd.ListenAsync())
{
switch (cmdEvent)
{
case StandardOutputCommandEvent stdOut:
await responseStream.WriteAsync(new ProcessReply { Message = stdOut.Text });
break;
}
}
await responseStream.WriteAsync(new ProcessReply { Message = "Process Complete" });https://stackoverflow.com/questions/62251866
复制相似问题