【发布时间】:2013-11-05 20:31:35
【问题描述】:
我尝试在 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 保持响应,并且通过调试我意识到每个线程同时退出。所以问题是为什么其他线程没有完成它们的部分。
【问题讨论】:
-
BytesRead 和 BytesProcessed 在 3 个线程之间通过引用共享?导致您的 while() 在 1 个线程完成后下载失败?
-
@KylePittman 不;它的写法很混乱,但是当调用方法时,这些变量的值会被复制到参数的存储中。每个线程都有自己的变量副本。不过,该代码非常具有误导性。
-
@KylePittman 但我猜这是一个简单的按值调用..
-
你真的不应该锁定所有重要的工作;它几乎违背了创建多个线程的目的。除了在任何给定的时间点坐在那里什么都不做之外,只有一个人在做任何事情。实际上,如果另一个停止并阻塞读取,您甚至无法让其中一个工作。
-
另外,您正在尝试下载 single 文件。这根本无法真正并行化。从同一个流中读取的三个线程并不比一个线程快;网络是瓶颈。并且发出三个不同的网络请求,以便三个线程可以分别读取三分之一的数据只会减慢您的速度,因为瓶颈(网络连接)必须完成三倍的工作。
标签: c# multithreading webrequest webresponse