[英]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.