C# 下载文件时无法更新进度条

C# 下载文件时无法更新进度条,c#,C#,我正在尝试制作一个简单的下载管理器。它可以工作。问题是,如果我添加一个progressbar来通知用户,我会得到这个异常 此流不支持查找操作 while ((readed = ReadFrom.Read(read, 0, read.Length)) > 0) { strLocal.Write(read, 0, readed); **UpdateProgress(ReadFrom.Length, st

我正在尝试制作一个简单的下载管理器。它可以工作。问题是,如果我添加一个progressbar来通知用户,我会得到这个异常

此流不支持查找操作

 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;
        }
这里怎么了

@编辑

@编辑2

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
。您可以在download方法中执行此操作,或者替换调用download的位置

在do work类中,您可以完成所有通常需要完成的工作,但在需要更新进度的情况下,您可以使用必要的值调用
ReportProgress

如果您查看上面的链接,还可以实现其他方法—如果您担心取消后台工作程序,或者存在错误或其他任何问题

编辑


如果您仍然收到错误,我刚刚意识到可能是您试图从
对象中提取长度。查看错误是否仍然存在。

如上所述,它与线程有关。因此,您需要在多个线程上分离操作,以便能够更新您的UI。您还可以使用async和Wait来解决此问题。下面是一篇关于它的好文章,这篇文章是关于做一些动作和更新UI的


我猜这里有一个线程问题。您是否尝试过使用BackgroundWorker而不是在UI线程上执行所有处理。所以进度条无法更新。有什么例外?progressBar1(比如MaxValue)的属性是什么?我已经按照你建议的使用线程更新了我的代码。我一整天都在上课,今天晚上我会尽量去看看。如果您想要其他参考资料,我将不胜感激。我将继续尝试解决方案,因为。我在返回worker时也会遇到相同的异常。请参见编辑2Alright,我给了您很多东西要看,但请尝试一下。@user3733078运气好吗?
// 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;
}