使用async和await实时更新数据



我已经尝试了这个答案中提到的代码:https://stackoverflow.com/a/27089652/

它工作得很好,我想用它来运行一个PowerShell脚本在for循环。GUI最初是冻结的,然后我尝试了这个答案中提到的代码:https://stackoverflow.com/a/35735760/

当PowerShell脚本在后台运行时,GUI不会冻结,尽管在for循环完成之前文本框中没有任何更新。我想看到实时更新的结果。下面是我正在运行的代码:

private async void run_click(object sender, RoutedEventArgs e)
{
Text1.Text = "";

await Task.Run(() => PS_Execution(Text1));
}
internal async Task PS_Execution(TextBox text)
{
PowerShell ps = PowerShell.Create();
ps.AddScript(script.ToString());
{
Collection<PSObject> results = ps.Invoke();
foreach (PSObject r in results)
{
text.Dispatcher.Invoke(() =>
{
text.Text += r.ToString();
});
await Task.Delay(100);
}                
}
}

也许我错过了重要的东西。请帮助我了解如何解决这个问题。

不要使用同步调用的ps.Invoke(),它将等待所有结果返回,而是使用ps.BeginInvoke()。然后订阅输出PSDataCollection的DataAdded事件,并使用该操作来更新您的ui。

private async void run_click(object sender, RoutedEventArgs e)
{
Text1.Text = "";
await Task.Run(() => PS_Execution(Text1));
}

internal async Task PS_Execution(TextBox text)
{
using PowerShell ps = PowerShell.Create();
ps.AddScript(script.ToString());
PSDataCollection<string> input = null;
PSDataCollection<string> output = new();
IAsyncResult asyncResult = ps.BeginInvoke(input, output);
output.DataAdded += (sender, args) =>
{
var data = sender as PSDataCollection<string>;
text.Dispatcher.Invoke(() =>
{
text.Text += data[args.Index];
});
};
}

最新更新