1

I am trying to make a simple download manager.and it works.The problem is that if i add a progressbar to inform the user I am getting this exception

This stream does not support seek operations

 while ((readed = ReadFrom.Read(read, 0, read.Length)) > 0)
            {

                strLocal.Write(read, 0, readed);
                **UpdateProgress(ReadFrom.Length, strLocal.Length);// throws exception**
            }

this the all code

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

What is wrong here?

@Edit

        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);
        }
user3733078
  • 249
  • 2
  • 11

2 Answers2

0

All of your operations are happening on the same thread. While you are doing the download, the application halts the UI from being updated. I typically use a BackgroundWorker to update progress bars for situations like this.

Here's an MSDN resource on background workers.

Based on your edit, here is some code for you:

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

You need to define the background worker in your class, and allow it to accept progress updates.

Then, wherever this method that requires the background worker is, you need to call RunWorkerAsync. You can do this inside the download method, or replace the spot where you call download.

In your do work class, you do all the stuff you normally would, but at the situation where you want to update progress, you can call ReportProgress with the necessary value.

If you look at the link above, there are other methods that can be implemented - if you are concerned about cancelling the background worker or if there is an error or anything else.

EDIT

If you are still receiving an error, I just realized that it may be the fact that you are trying to pull the length from a Stream object. Take a look at this question if the error persists.

Community
  • 1
  • 1
AdamMc331
  • 16,492
  • 10
  • 71
  • 133
  • I have updated my code as you suggested using threads .But Problem persisits – user3733078 Oct 14 '14 at 10:24
  • Okay. I am in class all day and will try to look this evening. If you would like another reference [here is a question I asked a while back that is really similar.](http://stackoverflow.com/questions/25814603/how-to-set-the-visibility-of-a-progessbar-in-wpf) – AdamMc331 Oct 14 '14 at 13:46
  • I would really appreciate.I will keep trying for a solution Because.I also get the same exception while backround worker.Please see edit 2 – user3733078 Oct 14 '14 at 14:05
  • Alright, I gave you a lot to look at, but give it a shot. – AdamMc331 Oct 14 '14 at 15:09
  • @user3733078 any luck? – AdamMc331 Oct 15 '14 at 12:44
0

As said above it has to do with the threads. So you need to seperate the actions over multiple threads to be able to update your UI. You can also use async and await to solve this issue. Below is a nice article about it, the article is about doing some action and updating the UI.

http://www.i-programmer.info/programming/c/1514-async-await-and-the-ui-problem.html

Willem
  • 398
  • 1
  • 6
  • 23