我有一个C#winform应用程序,其中的优化模型由OR-Tools解决。优化求解器具有将整个优化过程作为stdout发送的功能。
Slvr.EnableOutput();
Solver.ResultStatus restatus = Slvr.Solve();
但是,求解器不会自动打开控制台。 目前,我所做的是:
项目属性->应用程序->输出类型->控制台应用程序
,控制台从应用程序开始到运行结束都准备就绪。因此,该过程标准输出将自动显示。
我想要的是在运行以上代码的时候完全打开控制台,并显示求解器的标准输出。然后等待用户输入键以关闭控制台,然后继续执行主应用程序。
答案 0 :(得分:1)
我想您的问题是您正在尝试在GUI进程内将求解程序作为Winforms应用程序的一部分运行吗?但是Console
输出通常在Winforms应用程序中被禁用。您基本上有两种选择:
使用this older SO answer中所述的选项之一将控制台窗口附加到Winforms应用程序中
将应用程序分成两个exe文件:一个运行求解器的命令行程序,以及一个仅包含UI的Winforms部分。然后使用System.Diagnostics.Process.Start
作为单独的进程运行命令行部分,从而可以对输出重定向进行细粒度的控制。您可能需要UI将参数传递给命令行程序,例如通过使用临时文件。
第二个选项的工作量更多,特别是对于GUI和命令行工具之间的通信,但是可以以不阻塞GUI的方式实现,并且更容易解决求解器部分中的错误/程序崩溃,并且更健壮。如果您想引入并行化/一次运行多个求解器过程,通常性能会更好。
答案 1 :(得分:1)
Doc Brown 已经回答了您的问题,我添加这个只是为了提供一些我们在这里实现它的代码——这正是他的建议。我们有一个单独的 testPlugin.exe,从这里开始。通信是通过在文件系统上读取和写入的文件进行的。控制台输出在“输出处理程序”中被捕获
using System;
using System.Diagnostics;
using System.IO;
...
private void startTest()
{
int result = 2;
setFormStatus("working..."); // My method to inform the user with the form to wait.
getFormData(); // My method to get the data from the form
string errorMessage = null;
System.Diagnostics.Process testPlugInProcess = new System.Diagnostics.Process();
try
{
using (testPlugInProcess)
{
testPlugInProcess.StartInfo.UseShellExecute = false;
testPlugInProcess.StartInfo.FileName = System.IO.Path.Combine(assemblyDirectory, TestPlugInExe); // The name of the exe file
testPlugInProcess.StartInfo.CreateNoWindow = false;
testPlugInProcess.StartInfo.Arguments = getModelTestCommandLineArgs(); // My method to create the command line arguments
testPlugInProcess.StartInfo.RedirectStandardError = true;
testPlugInProcess.StartInfo.RedirectStandardOutput = true;
testPlugInProcess.OutputDataReceived += pluginTestOutputHandler;
testPlugInProcess.ErrorDataReceived += pluginTestOutputHandler;
testPlugInProcess.Start();
testPlugInProcess.BeginErrorReadLine();
testPlugInProcess.BeginOutputReadLine();
testPlugInProcess.WaitForExit();
result = testPlugInProcess.ExitCode;
}
setFormStatus("");
}
catch (Exception ex)
{
errorMessage = ex.Message;
}
testPlugInProcess = null;
}
控制台和错误输出在这里写入同一个文件,但您可以将它们分开。
插件处理程序如下所示:
private static void pluginTestOutputHandler(object sendingProcess,
DataReceivedEventArgs outLine)
{
if (!String.IsNullOrEmpty(outLine.Data))
{
for (int i = 0; i < numberOfTriesForWriting; i++)
{
try
{
using (StreamWriter sw = File.AppendText(lastPlugInTestTraceFilePath)) // The file name where the data is written.
{
sw.WriteLine(outLine.Data);
sw.Flush();
return;
}
}
catch (IOException)
{
System.Threading.Thread.Sleep(msToWaitBetweenTries);
}
}
}
}