0

我试图在 2-3 小时内解决此问题,但无法解决。我正在尝试分三个部分三个线程下载文件。问题是当一个部分完成时,其他线程停止下载。

Example: let's say i want to download 300kb 
part1->t1->100kb
part2->t2->100kb  //if this thread get completed then other two become unresponsive.
part3->t3->100kb     

我正在使用的代码(修改后的代码更短,但解决了我的问题)

//inside a function
            WebResponse wresp = wreq.GetResponse();
            long e1 = wresp.ContentLength / 3;
            long e2 = 2*e1;
            long e3 = wresp.ContentLength;
            wreq.Abort();
            wresp.Close();
            wreq = null;
            wresp = null;
            byte[] buff1 = new byte[1500];
            byte[] buff2 = new byte[1500];
            byte[] buff3 = new byte[1500];
            HttpWebRequest hr1 = (HttpWebRequest)WebRequest.Create(textBox1.Text);
            hr1.AddRange(0, e1-1);
            WebResponse wresp1 = hr1.GetResponse();
            HttpWebRequest hr2 = (HttpWebRequest)WebRequest.Create(textBox1.Text);
            hr2.AddRange(e1,e2-1);
            WebResponse wresp2 = hr2.GetResponse();
            HttpWebRequest hr3 = hr1;//(HttpWebRequest)WebRequest.Create(textBox1.Text);
            hr3.AddRange(e2,e3);
            WebResponse wresp3 = hr3.GetResponse();
            Stream response1 = wresp1.GetResponseStream();
            Stream  response2 = wresp2.GetResponseStream();
            Stream response3 = wresp3.GetResponseStream();
            Stream f1, f2, f3;
            f1 = File.Create("Part1");
            f2 = File.Create("Part2");
           f3 = File.Create("Part3");
            int bytesRead=0, bytesProcessed=0;
            long total1=e1, total2=e2-e1, total3=e3-e2;
            int x1=0, x2=0, x3=0;
            Thread t1 = new Thread(() =>download(hr1, wresp1, buff1,response1,f1,bytesRead, bytesProcessed,total1,x1));
            t1.Name = "1";
            Thread t2 = new Thread(() => download(hr2, wresp2, buff2, response2, f2, bytesRead, bytesProcessed,total2,x2));
            t2.Name = "2";
            Thread t3 = new Thread(() => download(hr3, wresp3, buff3, response3, f3, bytesRead, bytesProcessed, total3,x3));
            t3.Name = "3";
            t1.Start();
            t2.Start();
            t3.Start();
            }

        }
        }

    private download(HttpWebRequest hr2, WebResponse wresp2, byte[] buff, Stream response, Stream f,int bytesRead,long bytesProcessed,long total,int x)
    {
        do
        {
            lock (lockerObj)
            {
                bytesRead = response.Read(buff, 0, buff.Length);
                bytesProcessed += bytesRead;
                f.Write(buff, 0, bytesRead);
                x = Convert.ToInt32(Thread.CurrentThread.Name) - 1;
                pb[x].Invoke((Action)delegate
                {
                    pb[x].Value = Convert.ToInt32(bytesProcessed * 100 / total);

                });
                if (bytesProcessed >= total)
                {
                    Thread.CurrentThread.Abort();
                    break;
                }
                lb[x].Invoke((Action)delegate
                {
                    lb[x].Text = "Downloaded " + Convert.ToDouble((bytesProcessed * 100 / total)).ToString() + "%";
                    label4.Text = "thread" + (x + 1);
                });

            }
        } while (bytesProcessed<=total && bytesRead>=0 );
    }
    static readonly Object lockerObj=new Object(); //at global level

应用程序 ui 保持响应,并且从调试中我意识到每个线程同时退出。所以问题是为什么其他线程没有完成它们的部分。

在此处输入图像描述

4

2 回答 2

4

您在download方法的循环结束时有此条件:

while (bytesProcessed<=0 && bytesRead>0 );

那是你的问题。第一次通过循环,bytesProcessed按读取的字节数递增,使其大于 0,导致条件为假,循环退出。

您永远不会在循环中进行一次以上的迭代。

顺便说一句,并不是每个响应都会有一个有效的ContentLength. 网页通常不提供 Content-Length 标头,在这种情况下,该ContentLength属性将为 -1。即使页面确实提供了 Content-Length 标头,也不能保证它是正确的。因此,在一般情况下,您不能保证您已收到全部内容。

正如 Servy 在他的评论中指出的那样,在多个线程之间拆分下载不太可能提高性能,事实上很可能会导致下载速度变慢。如果站点看到您发出三个并发请求并决定限制或阻止您,则尤其如此。一般来说,您最好使用单个HttpWebRequest. 它更可靠,它简化了您的代码,并且可能比您编写的过于复杂的多线程版本执行得更好。

于 2013-11-05T21:32:26.353 回答
-3

我同意@Kyle Pittman。很可能 BytesRead 和 BytesProcessed 变量是您的问题的原因。

于 2013-11-05T20:44:18.590 回答