簡體   English   中英

異步等待-避免阻塞UI是正確的主意嗎?

[英]Async await - it is the right Idea to avoid a blocking UI?

我想使用await / async是確保響應式UI的最佳方法。 但是我似乎做錯了,因為我的應用程序始終凍結。

我嘗試執行的操作:按鈕已啟動,應等待長時間的操作。

public async Task CmdLoadExcel()
{
    // läd die excel datei
   string[] excelFiles = this.GetExcelFiles();
   ExcelLoader eloader = new ExcelLoader();
   await eloader.StartLoading(excelFiles);
   foreach (DataSet elem in eloader.Tables)
   {
       this.ActivateItem(new ExcelViewModel(elem) { DisplayName = elem.DataSetName });
   }
}

推出的課程:

public async Task StartLoading(string[] files)
        {
            foreach (string file in files)
            {
                Stopwatch swatch = new Stopwatch();
                swatch.Start();
                System.Threading.Thread.Sleep(5000);
                FileInfo finfo = new FileInfo(file);
                using (ExcelPackage package = new ExcelPackage(finfo))
                {
                // very long operation
                }
            } // For Each
        } // StartLoading

它只是在睡眠時停止,我不確定自己做錯了什么。

用async和await標記方法本身並不能真正做任何事情。 您需要等待任務:

這將有助於:

public async Task StartLoading(string[] files)
{
    return Task.Run(() =>
    {            
        foreach (string file in files)
        {
            Stopwatch swatch = new Stopwatch();
            swatch.Start();
            System.Threading.Thread.Sleep(5000);
            FileInfo finfo = new FileInfo(file);
            using (ExcelPackage package = new ExcelPackage(finfo))
            {
            // very long operation
            }
        } // For Each
    };
} // StartLoading

您的StartLoading方法似乎缺少任何await語句。 async關鍵字不能神奇地使方法能夠異步運行。 您可以await Task.Delay作為Thread.Sleep的異步替代品。 對於長時間的操作,如果受CPU限制,則可能需要生成一個新線程。 如果是IO綁定的,則取決於您是否有權使用可以使用的Async API。

請參閱MSDN Channel 9上有關Asysnc的三個基本技巧,以獲取一個好的介紹的開始。

問題在於您的StartLoading任務本身不是異步的。 您可以使用以下代碼解決此問題:

public Task StartLoading(string[] files)
{
    return Task.Factory.StartNew(() =>
        {
            foreach (string file in files)
            {
                Stopwatch swatch = new Stopwatch();
                swatch.Start();
                System.Threading.Thread.Sleep(5000);
                FileInfo finfo = new FileInfo(file);
                using (ExcelPackage package = new ExcelPackage(finfo))
                {
                        // very long operation
                }
            } // For Each    
        });
} // StartLoading

然后,您可以使用以下代碼:

public Task CmdLoadExcel()
{
    // läd die excel datei
   string[] excelFiles = this.GetExcelFiles();
   ExcelLoader eloader = new ExcelLoader();

   var task = eloader.StartLoading(excelFiles);
   return task.ContinueWith(t =>
            {
                foreach (DataSet elem in eloader.Tables)
                {
                    this.ActivateItem(new ExcelViewModel(elem) { DisplayName = elem.DataSetName });
                }
            });
 }

我懷疑問題可能在於“等待eloader.StartLoading(excelFiles);”行。 實際上在同一(UI)線程上運行。 您需要像下面那樣執行它。 這將導致該方法在ThreadPool線程上運行。

await Task.Run(eloader.StartLoading(excelFiles));

暫無
暫無

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

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