[英]I cant update progress bar while downloading a file
我正在嘗試制作一個簡單的下載管理器,並且它可以工作。問題是,如果我添加一個進度條來通知用戶,我將收到此異常
此流不支持搜索操作
while ((readed = ReadFrom.Read(read, 0, read.Length)) > 0)
{
strLocal.Write(read, 0, readed);
**UpdateProgress(ReadFrom.Length, strLocal.Length);// throws exception**
}
這是所有代碼
private void button1_Click(object sender, EventArgs e)
{
req = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
res = (HttpWebResponse)req.GetResponse();
Int64 contentlength = res.ContentLength;
WebClient wc = new WebClient();
Stream ReadFrom= wc.OpenRead(new Uri(url));
strLocal = new FileStream(@"E:\\xxx.tar.gz", FileMode.Create, FileAccess.Write, FileShare.None);
byte[]read=new byte[1024];
int readed = 0;
while ((readed = ReadFrom.Read(read, 0, read.Length)) > 0)
{
strLocal.Write(read, 0, readed);
UpdateProgress(ReadFrom.Length, strLocal.Length);
}
strLocal.Close();
ReadFrom.Close();
}
private void UpdateProgress(long Filesize, long readedBytes)
{
// progressBar1.Maximum = 100;
int downloaded =Convert.ToInt32((readedBytes * 100) / Filesize);
progressBar1.Value = downloaded;
}
怎么了
@編輯
HttpWebRequest req;
HttpWebResponse res;
Stream strLocal;
Stream ResponseStr;
byte[] bytes = null;
Thread thr;
delegate void UpdateCallBack(long l1, long l2);
public Form1()
{
InitializeComponent();
}
string url="https://www.unrealircd.org/downloads/Unreal3.2.10.3.tar.gz";
////string url2 = "http://www.microsoft.com/en-us/download/confirmation.aspx?id=34794&6B49FDFB-8E5B-4B07-BC31-15695C5A2143=1";
string filename = @"C:\\Unreal3.2.10.3.tar.gz";
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
thr = new Thread(download);
thr.Start();
}
private void download()
{
req = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
res = (HttpWebResponse)req.GetResponse();
Int64 contentlength = res.ContentLength;
ResponseStr = res.GetResponseStream();
strLocal = new FileStream(@"E:\\xxx.tar.gz", FileMode.Create, FileAccess.Write, FileShare.None);
byte[]read=new byte[1024];
int readed = 0;
while ((readed = ResponseStr.Read(read, 0, read.Length)) > 0)
{
strLocal.Write(read, 0, readed);
this.Invoke(new UpdateCallBack(this.UpdateProgress), new object[] {ResponseStr.Length,strLocal.Length });
}
strLocal.Close();
ResponseStr.Close();
}
private void UpdateProgress(long Filesize, long readedBytes)
{
int updated =Convert.ToInt32((readedBytes * 100) / Filesize);
progressBar1.Value = updated;
}
@ EDIT2
private void download()
{
req = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
res = (HttpWebResponse)req.GetResponse();
Int64 contentlength = res.ContentLength;
ResponseStr = res.GetResponseStream();
strLocal = new FileStream(@"E:\\xxx.tar.gz", FileMode.Create, FileAccess.Write, FileShare.None);
byte[]read=new byte[1024];
int readed = 0;
while ((readed = ResponseStr.Read(read, 0, read.Length)) > 0)
{
strLocal.Write(read, 0, readed);
backgroundWorker1.RunWorkerAsync();
// this.Invoke(new UpdateCallBack(this.UpdateProgress), new object[] {ResponseStr.Length,strLocal.Length });
}
strLocal.Close();
ResponseStr.Close();
}
private void UpdateProgress(long Filesize, long readedBytes)
{
int updated =Convert.ToInt32((readedBytes * 100) / Filesize);
progressBar1.Value = updated;
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
UpdateProgress(ResponseStr.Length, strLocal.Length);
}
您的所有操作都在同一線程上進行。 在進行下載時,該應用程序將停止UI更新。 對於這種情況,我通常使用BackgroundWorker更新進度條。
根據您的編輯,以下是適合您的代碼:
// At the class level, put this:
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerReportsProgress = true; // This means we want to send updates from the background worker.
// The DoWork method handles your time consuming task, which in this case is your download method. So you can try this:
private void Download()
{
bw.RunWorkerAsync();
}
// This should be called as a result:
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
// The worker who's progress will be updated.
BackgroundWorker worker = sender as BackgroundWorker;
req = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
res = (HttpWebResponse)req.GetResponse();
Int64 contentLength = res.ContentLength;
ResponseStr = res.GetResponseStream();
strLocal = new FileStream(@"E:\xxx.tar.gz", FileMode.Create, FileAccess.Write, FileShare.None);
byte[] read = new byte[1024];
int readed = 0;
while((readed = ResponseStr.Read(read, 0, read.Length)) > 0)
{
strLocal.Write(read, 0, readed);
// Update the worker (this uses the number you calculated)
worker.ReportProgress(Convert.ToInt32((ResponseStr.Length * 100) / strLocal.Length));
strLocal.Close();
ResponseStr.Close();
}
}
// This is called via worker.ReportProgress
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
您需要在您的課程中定義后台工作程序,並允許其接受進度更新。
然后,無論此方法需要后台工作人員在哪里,都需要調用RunWorkerAsync
。 您可以在下載方法中執行此操作,也可以替換調用下載的位置。
在do work類中,您可以執行通常的所有工作,但是在要更新進度的情況下,可以使用必要的值調用ReportProgress
。
如果您查看上面的鏈接,還有其他可以實現的方法-如果您擔心取消后台工作程序或出現錯誤或其他任何情況。
編輯
如果您仍然收到錯誤,我只是意識到您可能正在嘗試從Stream
對象提取長度。 如果錯誤仍然存在,請看這個問題 。
如上所述,它與線程有關。 因此,您需要將操作分開在多個線程上才能更新UI。 您還可以使用異步並等待以解決此問題。 以下是一篇不錯的文章,該文章是關於執行一些操作和更新UI的。
http://www.i-programmer.info/programming/c/1514-async-await-and-the-ui-problem.html
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.