在C#中与流程进行通信

时间:2018-01-19 19:08:58

标签: c# process

我需要使用标准输入和标准输出与外部可执行文件(ampl.exe)进行通信。这个exe在几分钟内进行计算,在控制台中有一些显示。它有一个提示,所以我可以在计算完成后立即使用其标准输入连续启动计算。

外部exe启动为:

var myProcess = new Process();
myProcess.StartInfo = new ProcessStartInfo("ampl.exe");
myProcess.StartInfo.CreateNoWindow = true;
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.RedirectStandardOutput = true;
myProcess.StartInfo.RedirectStandardError = true;
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.Start();

我使用myProcess.StandardInput和myProcess.StandardOutput(同步方式)与它进行通信。

我使用标准输入来启动计算,例如:

myProcess.StandardInput.WriteLine("solve;");

我想等待solve语句结束,在文件中获取结果,准备新的计算输入文件,然后启动第二次求解。

我的问题是我现在知道第一次计算何时完成,即exe在其标准输入中等待新命令的时间。 我发现的唯一方法是添加一个特定的显示命令,并等待它成为标准输出:

    myProcess.StandardInput.WriteLine("solve;");
    myProcess.StandardInput.WriteLine("print 'calculDone';");
    string output = myProcess.StandardOutput.ReadLine();
    while (!output.Contains("calculDone"))
    {
        output = myProcess.StandardOutput.ReadLine();
    }

还有另一种方法可以避免使用此显示命令来执行此操作吗?

编辑:遵循建议,我尝试了异步方式。但是我仍然需要打印'CalculDone'以了解解决方案声明何时结束。我没有在进程的标准输出中得到ampl.exe(即'ampl:')的提示。

AutoResetEvent eventEnd = new AutoResetEvent(false);

var myProcess = new Process();
myProcess.StartInfo = new ProcessStartInfo("ampl.exe");
myProcess.StartInfo.CreateNoWindow = true;
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.RedirectStandardOutput = true;
myProcess.StartInfo.RedirectStandardError = true;
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.EnableRaisingEvents = true;
myProcess.OutputDataReceived += (sender, e) =>
{
    if (e.Data == "commandDone")
    {
        eventEnd.Set();
    }
    else if (e.Data != null)
    {
        Console.WriteLine("ampl: {0}", e.Data);
    }
};

myProcess.Start();
myProcess.BeginOutputReadLine();

myProcess.StandardInput.WriteLine("solve;");
myProcess.StandardInput.WriteLine("print 'commandDone';");

eventEnd.WaitOne();

1 个答案:

答案 0 :(得分:1)

最好的选择是使用Processs.OutputDataReceived事件而不是紧密的while循环。这就像事件异步模式,您启动异步任务并等待事件回调告诉您已完成。异步任务的继续将放在事件处理程序中。记得在第一次关闭时取消订阅事件处理程序,否则当你不想要它时它会被触发。

我从未尝试过的另一个选项是Process.WaitForInputIdle()方法,但我不确定这是否适用于您的特定情况。如果是,则不需要在输入流中写入任何内容。