1

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.

4

4 回答 4

3

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
于 2013-04-15T13:05:12.657 回答
2

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.

于 2013-04-15T13:09:58.537 回答
1

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 });
                }
            });
 }
于 2013-04-15T13:05:25.953 回答
1

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));
于 2013-04-15T13:16:51.103 回答