3

ボタン、ラベル、ドロップダウンリストを含む単純なメトロアプリがあります。ドロップダウン リストには、読み取ることができるファイルのリストが含まれています。ボタンをクリックすると、選択したファイルの内容がラベルに読み込まれます。ファイルはドキュメント フォルダーにあります (つまり、WinRT の KnownFolders.DocumentsLibrary)。各ファイルは、WinRT API の StorageFile を表します。

ファイル読み込み方式は非同期方式(async/awaitを使用)です。非同期動作を証明するために、ファイル読み取りメソッドを長時間実行プロセスとして作成しました。したがって、この長時間実行される方法を実行している間、ドロップダウン リストを自由にクリックして、別のファイルを選択できるはずです。これは、ファイルの読み取り中に UI スレッドがブロックされないようにするためです。ただし、これは現在発生していません。まだ UI スレッドをブロックしているように見え、実行時間の長いメソッドが発生している間、ドロップダウン リストがフリーズします。ここで何か変なことをしているに違いない。UI が応答しない理由を教えてください。私のコードサンプルは以下です。

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; 
      }                
  }

}

4

1 に答える 1

7

UI スレッドで次のようなコードを実行すると、次のようになります。

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

その後// some more code、UI スレッドでも実行されます。これはまさにあなたの問題です。ファイルが読み取られた後、UI スレッドで長いループを実行するため、UI がフリーズします。

長時間実行される操作をシミュレートする場合は、いくつかの方法で実行できます。

  1. を使用してバックグラウンド スレッドでループを実行し、Task.Run()終了するまで非同期で待機します。

    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; 
     }
    
  2. CPU 時間を無駄にせずTask.Delay()、コードの実行を遅らせるために使用しないでください。

    private async Task<string> ReadFileAsync(IStorageFile storageFile)
    {
        var fileContent = await FileIO.ReadTextAsync(storageFile)
                                      .ConfigureAwait(false);
    
        await Task.Delay(TimeSpan.FromSeconds(10));
    
        return fileContent; 
     }
    
于 2012-04-03T22:01:31.127 に答える