当使用异步方法时, UI在winforms中无响应



所以我有一些方法,我想在我的表单加载时调用(理想情况下在构造函数中,但由于async/await在构造函数中不起作用,我正在使用Form_Load事件)。最初我使用一个单独的线程来做这项工作,这是伟大的。所有的事情都完成了,UI在工作完成的时候是响应的。然而,我读到使用async/await"更好","更少资源密集"。通常比创建单独的线程更可取。我猜原因是使用async/await使用更少的线程?

但是当我使用如下所示的方法时,UI被冻结/无响应,而需要几秒钟的函数正在运行。

在我的Form_Load事件中,我调用了一个同步方法:

private void Form_Load(object sender, EventArgs e)
{
CheckForDriver();
}

这里是CheckForDriver函数:

private void CheckForDriver()
{
System.Management.SelectQuery query = new SelectQuery("Win32_SystemDriver") { 
Condition = "Description = 'my driver'" };
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection drivers = searcher.Get();
if (drivers.Count > 0) // valid driver, go to next page
{
wizardControl.SelectedTab = startPage;
task = QueryDeviceAsync(false, new List<Button>());
}
}

其中task是定义为private Task task;的字段

这里是QueryDeviceAsync函数,需要一些时间的部分是switcher.GetDeviceAndSize()函数。

private async Task QueryDeviceAsync(bool enableForm, List<Button> buttons)
{
lastBackEnable = backBtn.Enabled;
lastNextEnable = nextBtn.Enabled;
EnableButtons(false, false);
this.Enabled = enableForm;
if (buttons != null)
{
foreach (Button button in buttons)
{
button.Enabled = false;
}
}
await Task.Run(() => switcher.GetDeviceAndSize()); // this function takes a few seconds and this is where the UI becomes unresponsive.
ThreadFinished?.Invoke(buttons);
}

然后在ThreadFinished事件处理程序中,我正在执行await task;以等待QueryDeviceAsync函数完成,此时我根据switcher.GetDeviceAndSize函数所做的更新一些UI内容。我也很困惑我是否可以/应该在异步方法中更新UI的东西,比如当我在QueryDeviceAsync函数中禁用buttons列表中的按钮时。我知道这在第二个线程中不起作用,必须在创建它们的线程上完成,但这运行没有问题。

我的主要问题是,表单仍然是无响应的,而我使用这些异步函数。当我使用一个单独的线程时,它工作得很好,所以我倾向于回到那个,但我想我会尝试找出这个方法。

在这种情况下,您需要将阻塞的同步工作卸载给工作线程。例如:

var search = new ManagementObjectSearcher(Query.ToString());
await Task.Run(() => search.Get());

最新更新