2016-03-22 7 views
0
私は(私はバックグラウンドダウンローダを使用したくない!) ここでは、ダウンロードのためのクラスコードでインターネットからファイルをダウンロードするアプリを開発するためにC#を使用してい

アプリケーションがハングアップしたときに使用HttpWebRequestの

public class DL 
{ 
    public event Progresses OnProgress; 
    Stopwatch stopwatch = new Stopwatch(); 

    public async void Get(string url, StorageFile destinationFile) 
    { 
     stopwatch.Reset(); 
     stopwatch.Start(); 
     HttpWebRequest request = (HttpWebRequest)WebRequest. 
      Create(url); 
     HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); 
     long size = response.ContentLength; 
     long downloaded = 0; 


     using (Stream inputStream = response.GetResponseStream()) 
     using (Stream outputStream = await destinationFile.OpenStreamForWriteAsync()) 
     { 
      byte[] buffer = new byte[1024]; 
      int bytesRead; 
      do 
      { 
       bytesRead = inputStream.Read(buffer, 0, buffer.Length); 
       downloaded += bytesRead; 
       outputStream.Write(buffer, 0, bytesRead); 
       int secondsRemaining = (int)(stopwatch.Elapsed.TotalSeconds 
        /downloaded * (size - downloaded)); 
       TimeSpan span = new TimeSpan(0, 0, 0, secondsRemaining); 
       string remainTime = string.Format("{0}:{1}:{2}", span.Hours, span.Minutes, span.Seconds); 
       OnProgress(remainTime); 
      } while (bytesRead != 0); 
     } 
    } 
} 

public delegate void Progresses(string text); 

これは、ファイルをダウンロードする方法です:

private async void btnDownload_Click(object sender, RoutedEventArgs e) 
{ 
    DL webGard = new DL(); 
    webGard.OnProgress += WebGard_OnProgress; 
    StorageFile destinationFile = await KnownFolders.MusicLibrary 
     .CreateFileAsync("r58.zip", CreationCollisionOption.GenerateUniqueName); 
    string url = "my url"; 
    webGard.Get(url, destinationFile); 
} 

private async void WebGard_OnProgress(string text) 
{ 
    System.Diagnostics.Debug.WriteLine(text); 
    var dispatcher = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher; 
    await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,() => 
    { 
     textBlock.Text = text; 
    }); 
} 

私はダウンロードボタンを押すと、アプリが現在ハングに行くと、私は、ユーザーに残り時間を表示したいと、このコードは上の作品、ダウンロードが終了するまで、それを使用することはできませんビジュアルスタジオでウィンドウを出力しますが、UIがハングして、結果をtextBlに表示できませんオッケー。

この問題を解決するにはどうすればよいですか? ありがとう

+0

「ボタン」をクリックするだけでなく、いくつかのブレークポイントを設定し、コードをステップ実行するのはどうですか?あなたがアプリケーションのコードのどこでハングアップするのかを教えてください。 – MethodMan

答えて

1

ここでの問題は、すべての正しい非同期コマンドを使用して起動していることです。これは素晴らしい方法です。残念ながら、実際にストリームからデータを読み込んでいるときは、このすべてを同期して実行しています。ここで私の意味は...

ストリームが初期化されると、ループを使用してデータの読み書きを開始します。 do/whileループを見ると、すべての操作が同期して行われていることがわかります。このループに2つの作業項目があり、あなたの重要なアプリケーションハングを引き起こしています。このライン:

bytesRead = inputStream.Read(buffer, 0, buffer.Length); 

と、この行:あなたはあなたの次のチャンクに戻ってサーバからの応答を待っている間、あなたのアプリケーションスレッドをブロックしようとしているあなたのループの各反復の間に

outputStream.Write(buffer, 0, bytesRead); 

データ。これは、サーバーが応答するのを待っているだけでなく、このデータをネットワーク経由で送信するための遅延を待っていることを意味します。さらに、このデータをファイルに書き戻すときに、ファイルシステムによってブロックされます。代わりに、ストリームのメソッドReadAsyncWriteAsyncを使用する必要があります。

この方法では、メモリ内の実際にデータを移動するときに、実際にはメインスレッドを非常に短い時間だけブロックします。その後、アプリケーションのUIスレッドが自由に自分の望むことを実行できる間に、ストリームを待って操作を終了します。

こちらがお役に立てば幸いです。

+0

ベストアンサーに感謝します。よく働く。おかげで多く – Ramtin

+0

問題はありません。これがあなたを助けてくれてうれしいです! –

関連する問題