我需要创建运行不同命令(PowerShell.exe、ipconfig 等)的应用程序,但是当调用 ExecuteCommand 时,UI 会冻结,直到工作完成。
尝试使用 await proc.StandardOutput.ReadToEndAsync() 运行该方法,但不起作用。 (它挂在提到的行上,不会在下一行继续)
我做错了什么?
提前致谢。
执行命令:
public static async Task<string> ExecuteCommand(string command)
{
try
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.RedirectStandardInput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
proc.StartInfo = procStartInfo;
proc.Start();
proc.WaitForExit();
var message = proc.StandardOutput.ReadToEndAsync();
//var error = await proc.StandardError.ReadToEndAsync();
proc.Close();
//var errorContent = error;
return message.Result;
}
catch (Exception objException)
{
return objException.Message;
}
}
记录器:
public void Logger(string value)
{
logtxt.AppendText("[" + DateTime.Now + "]: " + value + Environment.NewLine);
logtxt.SelectionStart = logtxt.Text.Length;
logtxt.ScrollToCaret();
}
处于活动状态:
private async Task<bool> IsActive()
{
string text = await ExecuteCommand("PowerShell.exe -Command \"Get-VPNconnection -AllUserConnection\"");
Logger(text);
...more code...
}
Form1_Shown(我从 Form_Load 中移出了以下代码,因为 UI 出现需要一些时间):
private void Form1_Shown(object sender, EventArgs e)
{
if (IsActive().Result)
{
...more code...
}
}
这是你的问题:
private void Form1_Shown(object sender, EventArgs e)
{
if (IsActive().Result)
{
...more code...
}
}
Result
属性是一个阻塞操作。它不仅会阻塞 UI 线程,更糟糕的是,它会导致死锁,因为异步流程中有 await
正在捕获 UI 上下文,因为它们没有配置 .ConfiguredAwait(false)
。解决这个问题的正确方法是走async-all-the-way:
private async void Form1_Shown(object sender, EventArgs e)
{
if (await IsActive())
{
...more code...
}
}
您可以通过阅读 Stephen Cleary 的著名文章不要阻止异步代码来了解有关此常见问题的更多信息。