Reputation: 43
I am working with grpc-dotnet in 3.1 for a project. On the server side, the grpc call will be executing a local system process (such as binaries or scripts). The issue I am having is the streaming of the redirected output from the process back over the grpc client. All I am getting right now is the first line of output. Here is my testing code.
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 });
}
}
On the client side, I am just using Streaming Server example code to read the lines from the stream.
await foreach (var message in call.ResponseStream.ReadAllAsync())
{
Console.WriteLine("Server Out: " + message.Message);
}
Any ideas why I am only getting 1 line of the process output from the redirected process output. I am only seeing the the one line in the logger output as well.
Upvotes: 0
Views: 538
Reputation: 9414
This might be because you're writing to the ResponseStream
from an event handler, which is not necessarily being called on the right async context for the stream.
Take a look at CliWrap which wraps the whole process execution thing in a very nice API, including a ListenAsync
method which returns an IAsyncEnumerable
that you can await foreach
over and write the output to the stream.
Borrowing from the README, it would look something like this:
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" });
Upvotes: 1