Subway WinRT app still blocks UI thread when called via async method

I have a simple metro app that contains a button, a shortcut and a dropdown. The dropdown list contains a list of files that I can read. When I click the button, the contents of the selected files are read into the label. The files are located in the Documents folder (for example, WinRTs KnownFolders.DocumentsLibrary). Each file is a StorageFile in the WinRT API.

The file reader method is an asynchronous method (uses async / await). To prove the asynchronous behavior, I made the file reading method a lengthy process. So while doing this long running method, I should be able to freely click on the dropdown and select a different file. This is because the UI thread should not block while reading the file. However, this is not currently happening. It still seems to be blocking the UI thread and the combobox becomes frozen when a long running process occurs. I must be doing something strange here. Could you please tell me why the UI is not responsive? Below is a sample code.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace FileAccess
{
    public sealed partial class MainPage : Page
    {
       private readonly StorageFolder storageFolder;       

       public MainPage()
       {
        this.InitializeComponent();
        storageFolder = KnownFolders.DocumentsLibrary;
        AddFiles();
       }

       private async void AddFiles() //Add files to the drop down list
       {
        var filesList = await storageFolder.GetFilesAsync();
        IEnumerable<FileItem> fileItems
            = filesList.Select(x => new FileItem(x.Name, x.Name));

        cboSelectFile.ItemsSource = fileItems;
        cboSelectFile.SelectedIndex = 0;
       }


      private async void BtnReadFile_Click(object sender, RoutedEventArgs e)
      {
        IStorageFile storageFile = await storageFolder.GetFileAsync((string)cboSelectFile.SelectedValue);           

        if (storageFile != null)
        {
            LblReadFile.Text = await ReadFileAsync(storageFile); //long running method**************
        }
      }


      private async Task<string> ReadFileAsync(IStorageFile storageFile) //long running method**************
      {
        var fileContent = await FileIO.ReadTextAsync(storageFile);

        for (Int64 i = 0; i < 10000000000; i++)
        {
        }

        return fileContent; 
      }                
  }

      

}

+3


source to share


1 answer


If you execute code like this on the UI thread:

var whatever = await DoSomethingAsync();
// some more code

      

Then // some more code

it will also execute on the UI thread. This is exactly your problem. After reading the file, you are doing a long loop on the UI thread, so the UI hangs.



If you want to simulate some long running operation, you can do it in several ways:

  • Loop on a background thread with Task.Run()

    and asynchronously wait for it to complete:

    private async Task<string> ReadFileAsync(IStorageFile storageFile)
    {
        var fileContent = await FileIO.ReadTextAsync(storageFile);
    
        await Task.Run(() => { for (Int64 i = 0; i < 10000000000; i++) {} });
    
        return fileContent; 
     }
    
          

  • Don't waste CPU time and don't use Task.Delay()

    to delay code execution:

    private async Task<string> ReadFileAsync(IStorageFile storageFile)
    {
        var fileContent = await FileIO.ReadTextAsync(storageFile)
                                      .ConfigureAwait(false);
    
        await Task.Delay(TimeSpan.FromSeconds(10));
    
        return fileContent; 
     }
    
          

+7


source







All Articles