2012-12-23 60 views
2

爲什麼當我執行按鈕單擊事件並在打開文本文件時寫入文本文件的任何原因仍然是掛起UI線程。寫作完成之前無法做任何事情。在Windows 8中寫入文件時的異步

private async void WriteFileClick(object sender, RoutedEventArgs e) 
    { 
     string fileName = @"asyn3cfile.txt"; 
     string text = "Hello async, this was written while you were doing something else in the UI"; 

     StorageFolder storageFolder = KnownFolders.DocumentsLibrary; 
     var writtenFile = await storageFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting); 

     using (IRandomAccessStream randomAccessStream = await writtenFile.OpenAsync(FileAccessMode.ReadWrite)) 
     { 
      Stream stream = randomAccessStream.AsStreamForWrite(); 
      stream.Seek(0, SeekOrigin.Begin); 
      WriteFileTextAsync(text, stream); 
      await stream.FlushAsync(); 
      await randomAccessStream.FlushAsync(); 
     } 
     Debug.WriteLine("{0} was created", fileName); 
    } 

    private async static void WriteFileTextAsync(string text, Stream stream) 
    { 
     for (int i = 0; i < 100; i++) 
     { 
      var fileText = string.Format("{0} in process {1}\n", text, i); 
      byte[] textBytes = Encoding.UTF8.GetBytes(fileText); 
      stream.SetLength(stream.Length + textBytes.Length); 

      await stream.WriteAsync(textBytes, 0, textBytes.Length); 
      new System.Threading.ManualResetEvent(false).WaitOne(100); 
     } 
    } 

XAML

<Button x:Name="WriteFileInDocumentsButton" Content="Write a text file" Click="WriteFileClick"/> 

任何原因?

+0

你能告訴你如何/在哪裏調用這些方法嗎?也許某處你有阻止主線程的任務的等待電話? –

+0

它是通過按鈕事件點擊調用的。 –

回答

3

你應該改變:

private async static void WriteFileTextAsync(string text, Stream stream) 
{ 
    for (int i = 0; i < 100; i++) 
    { 
     var fileText = string.Format("{0} in process {1}\n", text, i); 
     byte[] textBytes = Encoding.UTF8.GetBytes(fileText); 
     stream.SetLength(stream.Length + textBytes.Length); 

     await stream.WriteAsync(textBytes, 0, textBytes.Length); 
     new System.Threading.ManualResetEvent(false).WaitOne(100); 
    } 
} 

private async static Task GetFileTextAsync(string text, Stream stream) 
{ 
    StringBuilder sb = new StringBuilder(); 
    for (int i = 0; i < 100; i++) 
    { 
     sb.AppendLine(string.Format("{0} in process {1}\n", text, i));    
    } 
    await stream.WriteAsync(textBytes, 0, textBytes.Length); 
} 

這將有助於節省一些開銷,但之後更重要的是,你必須改變:

using (IRandomAccessStream randomAccessStream = await writtenFile.OpenAsync(FileAccessMode.ReadWrite)) 
    { 
     Stream stream = randomAccessStream.AsStreamForWrite(); 
     stream.Seek(0, SeekOrigin.Begin); 
     WriteFileTextAsync(text, stream); 
     await stream.FlushAsync(); 
     await randomAccessStream.FlushAsync(); 
    } 
    Debug.WriteLine("{0} was created", fileName); 

以包含的await關鍵詞在WriteFileAysnc方法調用上。

using (IRandomAccessStream randomAccessStream = await writtenFile.OpenAsync(FileAccessMode.ReadWrite)) 
    { 
     Stream stream = randomAccessStream.AsStreamForWrite(); 
     stream.Seek(0, SeekOrigin.Begin); 
     **await** WriteFileTextAsync(text, stream); 
     await stream.FlushAsync(); 
     await randomAccessStream.FlushAsync(); 
    } 
    Debug.WriteLine("{0} was created", fileName); 
1

你的代碼有一些bug。您不在等待WriteAsync,並且WriteFileTextAsync應該返回一個任務,並等待。

如果你只是寫字符串,你會發現它更容易使用FileIO輔助方法。

+0

這是我原來的帖子。我一直在等待這些方法。 UI仍然被阻止。我知道,但那只是一次寫正確的?如果我想在寫作時打開文件,該怎麼辦? –

+0

您仍需要WriteFileTextAsync才能返回Task而不是void,並等待該調用。切換到FileIO壽,它更容易! –

+0

糾正我,如果我錯了,但FileIO只寫一個大時間在一個巨大的字符串,對吧? –