简体   繁体   English

异步等待-避免阻塞UI是正确的主意吗?

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

I thaught that using await / async is the best Idea to ensure a responsive UI. 我想使用await / async是确保响应式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. 用async和await标记方法本身并不能真正做任何事情。 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. 您的StartLoading方法似乎缺少任何await语句。 The async keyword does not magically make a method able to run asyncronously. async关键字不能神奇地使方法能够异步运行。 You can await a Task.Delay as an async-alterative to your Thread.Sleep . 您可以await Task.Delay作为Thread.Sleep的异步替代品。 For your very long operation, you probably need to spawn a new thread if it is CPU bound. 对于长时间的操作,如果受CPU限制,则可能需要生成一个新线程。 If it is IO bound, then it is a matter of whether you have access to an Async API that you can use. 如果是IO绑定的,则取决于您是否有权使用可以使用的Async API。

See Three Essential Tips For Asysnc on MSDN Channel 9 for the start of a good introduction. 请参阅MSDN Channel 9上有关Asysnc的三个基本技巧,以获取一个好的介绍的开始。

The problem is that your StartLoading task itself isn't asynchronous. 问题在于您的StartLoading任务本身不是异步的。 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);" 我怀疑问题可能在于“等待eloader.StartLoading(excelFiles);”行。 is actually running on the same (UI) thread. 实际上在同一(UI)线程上运行。 You need to execute it like below. 您需要像下面那样执行它。 This will cause the method to be run on a ThreadPool thread. 这将导致该方法在ThreadPool线程上运行。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM