C#窗口异步调用DOS程序并返回结果
郝伟 2022/08/17
本文章包括两在核心内容:
经测试,以下代码效果非常好,可以达到以下效果:
代码如下:
/// <summary> /// 用于执行第三方程序,并返回执行结果。 /// </summary> /// <param name="exefile_path">可执行的程序的路径。</param> /// <param name="arglist">可执行程序的参数列表,默认为 ""。</param> /// <param name="timeout">超时时间,单位秒,默认为10秒。</param> /// <returns></returns> public static string RunCommand(string exefile_path, string arglist = "", double timeout = 10) { // 1. 保证可执行程序存在,否则报错。 var fullpath = Path.GetFullPath(exefile_path); if (!File.Exists(fullpath)) { return "Error: 转换器模块不存在。"; } // 2. 使用Process类初始化一个进程用于处理DOS程序 Process p = new Process(); p.StartInfo.FileName = Path.GetFullPath(exefile_path); // 获得全路径 p.StartInfo.Arguments = arglist; // 参数列表已经格式化,如: "a b.txt" c 10 p.StartInfo.UseShellExecute = false; // 不显示用户界面 p.StartInfo.RedirectStandardOutput = true; // 是否重定位输出于当前输出。 p.StartInfo.CreateNoWindow = true; // 不创建新窗口。 // 3. 任务执行 为防止出错,使用了 try-catch-finally 逻辑进行容错 string retInfo = ""; try { // 3.1 开始任务,此时是异步执行,所以不会卡住 if (p.Start()) { // 3.2 强制同步等待指定时间,不限时也可以,但有有隐患所以还是加上了 p.WaitForExit((int)(timeout * 1000)); // 3.3 到时间如果还没有结束,就将任务线程关闭 if (!p.HasExited) p.Kill(); // 3.4 无计是否执行完成都可以从控制台读取出输出的信息 retInfo = p.StandardOutput.ReadToEnd(); } } // 4. 如果出现异常,则将错误信息返回,目前尚未发现有异常出现。 catch (Exception ex) { Console.WriteLine(ex.Message);//捕获异常,输出异常信息 retInfo = "Error: " + ex.Message; } // 5. 强制关闭线程以节省资源 finally { if (p != null) p.Close(); } // 6. 返回执行结果, <表示开始,>表示结果, E表示错误 return retInfo; }
异步调用可以保证界面不会卡死,实现代码如下:
private async void button1_Click(object sender, EventArgs e) { var result = ""; await Task.Run(() => { DosArguments da = DosArguments.New("abc", "info"); result = RunCommand("Converter.exe", da.ToDosString(), (double)numericUpDown1.Value); }); textBox1.Text += result + "\r\n"; }
异步的原理很简单,就是先调用,有了结果返回后再处理结果。
扩展 异步任务的目标可以理解为主界面有n个可并行的工作,安排了n个线程去执行,然后任何一个线程执行完后会返回到主线程,主线程再执行之前定好的尾工作。