2012-04-03 4 views
3

간단한 메트로 앱에 단추, 레이블 및 드롭 다운 목록이 있습니다. 드롭 다운 목록에는 읽을 수있는 파일 목록이 들어 있습니다. 버튼을 클릭하면 선택한 파일의 내용이 레이블로 읽혀집니다. 파일은 문서 폴더 (예 : WinRT의 KnownFolders.DocumentsLibrary)에 있습니다. 각 파일은 WinRT API의 StorageFile을 나타냅니다.비동기 메서드를 통해 호출하면 WinRT 메트로 앱이 여전히 UI 스레드를 차단합니다.

파일 읽기 방법은 비동기 방식 (async/await 사용)입니다. 비동기 동작을 증명하기 위해 파일 읽기 메서드를 장기 실행 프로세스로 만들었습니다. 따라서이 장기 실행 방법을 실행하는 동안 드롭 다운 목록을 자유롭게 클릭하고 다른 파일을 선택할 수 있어야합니다. 이는 UI 스레드가 파일을 읽는 동안 차단되지 않아야하기 때문입니다. 그러나 이것은 현재 일어나지 않습니다. 그것은 여전히 ​​UI 스레드를 차단하는 것, 그리고 장기 실행 메서드가 발생하는 동안 드롭 다운 목록 고정됩니다. 나는 이상한 무엇인가 여기에서해야하고있다. UI가 응답하지 않는 이유를 말씀해 주시겠습니까? 내 코드 샘플은 다음과 같습니다.

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

그런 다음 // some more code 또한 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 스레드에서 긴 루프를 실행하므로 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' 메쏘드는 작업을 반환하기 때문에 전체 내용을 async로 가정했습니다. –

관련 문제