簡體   English   中英

使用異步方法時,UI 在 winforms 中無響應

[英]UI is unresponsive in winforms when using async methods

所以我有幾個方法想在我的表單加載時調用(最好在構造函數中調用,但由於 async/await 在構造函數中不起作用,我正在使用Form_Load事件)。 最初我使用一個單獨的線程來完成這項工作,效果很好。 一切都已完成,並且在工作完成時 UI 是響應式的。 但是,我讀到使用 async/await 是“更好”、“資源密集度較低”,並且通常比創建單獨的線程更受歡迎。 我猜原因是使用 async/await 使用的線程更少?

但是當我如下圖所示使用此方法時,UI 被凍結/無響應,而 function 正在運行需要幾秒鍾。

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

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

然后這是我的CheckForDriver function:

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 function,需要一些時間的部分是switcher.GetDeviceAndSize() function。

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 function 完成,此時我根據switcher.GetDeviceAndSize function 所做的更新一些 UI 內容。 我也對我是否可以/應該以異步方法更新 UI 內容感到困惑,例如當我禁用QueryDeviceAsync function 中buttons列表中的按鈕時。我知道這在第二個線程中不起作用,必須是在創建它們的線程上完成,但這運行沒有問題。

我的主要問題是當我使用這些異步函數時表單仍然沒有響應。 當我使用單獨的線程時它工作正常,所以我傾向於 go 回到那個,但我想我會嘗試找出這個方法。

在這種情況下,您需要將阻塞的同步工作卸載到工作線程。 例如:

var search = new ManagementObjectSearcher(Query.ToString());

await Task.Run(() => search.Get());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM