2016-08-29 8 views
0

私のWinRTアプリケーション用の簡単なアルゴリズムを作った。クラスのWebレスポンスのストリームを持つ。私は "ProgressChanged"イベントと非同期にファイルをダウンロードする必要があります。ここに私の方法は次のとおりです。進捗値を持つ非同期ダウンロードアルゴリズム

public async void DownloadFileAsync(string uri, StorageFile path) 
{ 
     var request = WebRequest.CreateHttp(uri); 
     var response = await request.GetResponseAsync(); 
     if (response != null) 
     { 
      long totalBytes = response.ContentLength; 
      long writedBytes = 0; 
      using(var webStream = response.GetResponseStream()) 
      using (IRandomAccessStream stream = await path.OpenAsync(FileAccessMode.ReadWrite)) 
      using (DataWriter dataWriter = new DataWriter(stream)) 
      { 
       await Task.Run(() => 
       { 
        int b; 
        while ((b = webStream.ReadByte()) != -1) 
        { 
         dataWriter.WriteByte((byte)b); 
         writedBytes++; 
         if (writedBytes % (totalBytes/100) == 0) 
          OnProgressChanged(new ProgressEventArgs(writedBytes/(totalBytes/100))); 
        } 
       }); 
       await dataWriter.StoreAsync(); 
       OnDownloadComplete(new EventArgs()); 
      } 
     } 
} 

ProgressEventArgsコード:

public class ProgressEventArgs : EventArgs 
{ 
    public ProgressEventArgs(double percentage) 
    { 
     Percentage = percentage; 
    } 
    public double Percentage { get; set; } 
} 

これが働いています。しかし、私はそれが速くなければならないと思います。シーケンシャルバイトの読み込みが遅すぎます。どうすれば速くすることができますか?私は初心者です。助けてください。

+1

あなたが初心者であるという事実は問題ではありませんので気にしません。多分あなたは遅いネットワークを持っていますか?正確に何が遅いですか?ダウンロード?ファイルを読む?遅い特定の部品/ラインを参照することはできますか?方法全体が遅くなっていますか? – MichaelThePotato

+0

ブロック中のストリームを読み込みます。私は、それは良い解決策ではないと思う。私が間違っている? – Alexey

答えて

1

大量のデータを1バイトずつ読み書きすると速度が低下することがあります.1MBのファイルをダウンロードするための何百万ものメソッド呼び出しがあります。あなたは、チャンク内のデータを読み取るために代わりにバッファを使用する必要があります。

... 
long totalBytesRead = 0; 

// Allocate a 4KB buffer for each read/write  
byte[] buffer = new byte[4 * 1024]; 
int bytesRead; 

// Read up to 4KB of data, check if any data read 
while ((bytesRead = webStream.Read(buffer, 0, buffer.Length)) > 0) { 
    // Write the 4KB (or less) buffer 
    dataWriter.WriteBuffer(buffer.AsBuffer(0, bytesRead)); 
    totalBytesRead += bytesRead; 

    // TODO: Report progresss 
}  
.... 

最適なバッファサイズは、多くのものに依存し、4KBのバッファは問題ないはずです。 Hereあなたはより多くの情報を得ることができます。

1

あなたのコードを確認したところ、ダウンロード時にバイトの読み方が遅くなる可能性があることがわかったので、BackgroundDownloaderクラスを使用するようアドバイスします。ビデオ、音楽、画像などの大きなリソースを処理することができます。
私はデモを作成し、それがあなたに役立つことを願っています。

XAML一部:背後

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <Button Content="Download File" Click="DownloadFile"/> 
</Grid> 

コード:

public sealed partial class MainPage : Page 
    { 
     public MainPage() 
     { 
      this.InitializeComponent(); 
     } 


     private async void DownloadFile(object sender, RoutedEventArgs e) 
     { 
      try 
      { 
       Uri source = new Uri("http://h.hiphotos.baidu.com/zhidao/pic/item/6d81800a19d8bc3ed69473cb848ba61ea8d34516.jpg"); 
       string destination = "dog.jpg"; 

       StorageFile destinationFile = await KnownFolders.PicturesLibrary.CreateFileAsync(
        destination, CreationCollisionOption.GenerateUniqueName); 

       BackgroundDownloader downloader = new BackgroundDownloader(); 
       DownloadOperation download = downloader.CreateDownload(source, destinationFile); 
       await download.StartAsync(); 
       // Attach progress and completion handlers. 
       //HandleDownloadAsync(download, true); 
       BackgroundDownloadProgress currentProgress = download.Progress; 

       double percent = 100; 
       if (currentProgress.TotalBytesToReceive > 0) 
       { 
        percent = currentProgress.BytesReceived * 100/currentProgress.TotalBytesToReceive; 
       } 

      } 
      catch (Exception ex) 
      { 
       // LogException("Download Error", ex); 
      } 
     } 
    } 

私はそれをテストしてきたし、それが動作します。詳細については、official sampleを参照することもできます。

よろしくお願いします。

+0

背景APIのダウンロードは混乱します。バックグラウンドのダウンロードが必要な場合を除き、使用しないことをお勧めします。 –

関連する問題