所以我有一些方法,我想在我的表单加载时调用(理想情况下在构造函数中,但由于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());