I thaught that using await / async is the best Idea to ensure a responsive UI. But I seem to do something wrong, because my Application freezes anyway.
Wht I Try to do: A Button is launched and should await a long lasting operation.
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 });
}
}
The launched Class:
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
It simply halts at the sleep and I am unsure what I have done wrong.
Marking methods with async and await doesn't really do anything by itself. You need to await a task:
This would help:
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
Yor StartLoading
method appears to be lacking any await
statements. The async
keyword does not magically make a method able to run asyncronously. You can await
a Task.Delay
as an async-alterative to your Thread.Sleep
. For your very long operation, you probably need to spawn a new thread if it is CPU bound. If it is IO bound, then it is a matter of whether you have access to an Async API that you can use.
See Three Essential Tips For Asysnc on MSDN Channel 9 for the start of a good introduction.
The problem is that your StartLoading task itself isn't asynchronous. You can fix this using the following code:
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
Then you can use the code as follows:
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 });
}
});
}
I suspect the issue might be that the line "await eloader.StartLoading(excelFiles);" is actually running on the same (UI) thread. You need to execute it like below. This will cause the method to be run on a ThreadPool thread.
await Task.Run(eloader.StartLoading(excelFiles));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.