2016-03-22 11 views
0

i C# bin mit einer App zu entwickeln, die eine Datei aus dem Internet herunterladen (Ich will nicht Hintergrund-Downloader verwenden!) Hier Klassencode zum Download:App hängt beim Gebrauch 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); 

und dies ist, wie eine Datei zum Download:

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; 
    }); 
} 

Wenn ich Download-Button drücken, App geht zur Zeit zu hängen und kann es nicht bis Download endet verwenden, möchte ich verbleibende Zeit Benutzer zeigen, und dieser Code funktioniert auf Ausgabefenster in Visual Studio, aber UI ist gehängt und kann keine Ergebnisse in textBl anzeigen ock.

Wie kann ich dieses Problem beheben? Danke

+0

Wie wäre es, wenn Sie nicht nur auf die Schaltfläche klicken, sondern einige Haltepunkte setzen und den Code durchgehen? kannst du uns sagen, wo im Code deine App anfängt aufzuhängen ..? – MethodMan

Antwort

1

Das Problem hier ist, dass Sie alle richtigen Async-Befehle verwenden, um zu starten, was großartig ist. Wenn Sie tatsächlich die Daten aus dem Stream lesen, tun Sie dies alles synchron. Hier ist, was ich meine ...

Sobald Sie Ihre Streams initialisiert, beginnen Sie lesen und schreiben Daten mit einer Schleife. Wenn Sie Ihre Do/While-Schleife betrachten, werden Sie sehen, dass alle Operationen synchron ausgeführt werden. Es gibt zwei Arbeitsaufgaben in dieser Schleife, die dazu führen, dass Ihre App hängen bleibt. Diese Zeile:

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

und diese Linie:

outputStream.Write(buffer, 0, bytesRead); 

Während jeder Iteration der Schleife werden Sie Ihre Anwendungsthread blockieren, während Sie auf eine Antwort vom Server mit Ihrem nächsten Brocken warten von Daten. Dies bedeutet, dass Sie nicht nur auf dem Server warten, um zu antworten, Sie warten auch auf die Verzögerung, um diese Daten über das Netzwerk zu übertragen. Darüber hinaus werden Sie dann vom Dateisystem blockiert, wenn Sie diese Daten in Ihre Datei zurückschreiben. Stattdessen sollten Sie die Methoden ReadAsync und WriteAsync des Streams verwenden.

Auf diese Weise blockieren Sie eigentlich nur für eine sehr kurze Zeit Ihren Hauptthread, während Sie die Daten tatsächlich im Speicher bewegen. Dann sind Sie wieder bereit, auf die Streams zu warten, um ihre Operationen zu beenden, während Ihr Anwendungs-UIhread frei ist, zu tun, was er will.

Ich hoffe, das hilft!

+0

Danke für die beste Antwort. funktioniert super. Vielen Dank – Ramtin

+0

Kein Problem. Ich bin froh, dass dir das geholfen hat! –

Verwandte Themen