簡體   English   中英

使用HttpWebRequest時應用程序掛起

[英]App hangs when use HttpWebRequest

我正在使用C#開發可從互聯網下載文件的應用程序(我不想使用后台下載器!)這是要下載的類代碼:

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

當我按下下載按鈕時,應用當前處於掛起狀態,直到下載結束后才可以使用它,我想向用戶顯示剩余時間,此代碼在Visual Studio的“輸出”窗口中有效,但UI掛起並且無法顯示結果textBlock。

我該如何解決這個問題? 謝謝

這里的問題是您正在使用所有正確的異步命令來啟動,這很棒。 不幸的是,當您實際從流中讀取數據時,您正在同步進行所有操作。 這就是我的意思...

一旦初始化了流,就可以開始使用循環讀取和寫入數據。 如果查看do / while循環,您將看到所有操作都正在同步進行。 此循環中有兩個工作項導致您的應用程序嚴重掛起。 這行:

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

這行:

outputStream.Write(buffer, 0, bytesRead);

在循環的每次迭代期間,您將在等待服務器返回下一個數據塊的響應時阻塞應用程序線程。 這意味着您不僅在等待服務器上的答復,而且還在等待通過網絡傳輸此數據的延遲。 最重要的是,當您將該數據寫回到文件中時,文件系統將阻止您。 相反,您應該使用流的ReadAsyncWriteAsync方法。

這樣,實際上在內存中移動數據時,實際上只在很短的時間內阻塞了主線程。 然后,您將回到等待流完成其操作的狀態,而應用程序UI線程可以自由執行所需的操作。

我希望這有幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM