2012-04-03 6 views
3

私は単純なメトロアプリにボタン、ラベル、ドロップダウンリストが含まれています。ドロップダウンリストには、私が読むことができるファイルのリストが含まれています。ボタンをクリックすると、選択したファイルの内容がラベルに読み込まれます。ファイルはDocumentsフォルダにあります(WinRTのKnownFolders.DocumentsLibraryなど)。各ファイルは、WinRT APIのStorageFileを表します。非同期メソッドによって呼び出されたとき、WinRTメトロアプリはUIスレッドをブロックします

ファイル読み取りメソッドは、非同期メソッドです(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; 
     }     
    } 

}

+0

まあ、神聖な牛、そのディレクトリにいくつのファイルがありますか? –

+0

@HansPassantほんの少しですが、私はあなたの質問の理由が不思議ですか? – Spock

答えて

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

それは明らかな答えのように思えましたが、私はその包含方法もまた '待たれている 'という事実を説明する方法を知らなかった。 –

+0

@RitchMelton、それは何も変わらない。なぜあなたはそれがどうだろうと思いますか? – svick

+0

無知。 'async'とマークされた' await'メソッドは、タスクを返すので、その内容全体が非同期であると仮定しました。 –

関連する問題