[英]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);
在循環的每次迭代期間,您將在等待服務器返回下一個數據塊的響應時阻塞應用程序線程。 這意味着您不僅在等待服務器上的答復,而且還在等待通過網絡傳輸此數據的延遲。 最重要的是,當您將該數據寫回到文件中時,文件系統將阻止您。 相反,您應該使用流的ReadAsync和WriteAsync方法。
這樣,實際上在內存中移動數據時,實際上只在很短的時間內阻塞了主線程。 然后,您將回到等待流完成其操作的狀態,而應用程序UI線程可以自由執行所需的操作。
我希望這有幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.