Http下载线程直接退出字节读取循环
Download thread over Http directly exits from byte-reading loop
我有一个项目要通过 Http 使用多线程下载。它会部分下载内容。
对于某些网址和下载速度较慢的情况,部分下载线程在while循环中等待时间过长而没有获取到数据,几次后线程直接退出而没有执行while循环后的代码。我不明白怎么可能。
My code:
void DownloadProcedure()
{
file = new FileStream(this.FullPath,
FileMode.Create, FileAccess.ReadWrite);
#region Request-Response
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12
| SecurityProtocolType.Ssl3;
HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest;
req.Accept = "*/*";
req.Timeout = 3000;
req.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
req.AllowAutoRedirect = true;
req.MaximumAutomaticRedirections = 5;
req.ServicePoint.ConnectionLimit += 2;
req.ServicePoint.Expect100Continue = true;
req.ProtocolVersion = HttpVersion.Version10;
if (rangeAllowed)
req.AddRange(from, to);
resp = req.GetResponse() as HttpWebResponse;
#endregion
#region Some Stuff
contentLength = resp.ContentLength;
if (rangeAllowed && contentLength != to - from + 1)
throw new Exception("Incorrect response content");
tempStream = resp.GetResponseStream();
int bytesRead = 0;
byte[] buffer = new byte[4096];
stp.Start();
#endregion
#region Procedure Loop
while ((bytesRead = tempStream.Read(buffer, 0, buffer.Length)) > 0)
{
while (wait) ;
if (totalBytesRead + bytesRead > contentLength)
bytesRead = (int)(contentLength - totalBytesRead);
file.Write(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
last40Speed[counter] = (int)(totalBytesRead / Math.Ceiling(stp.Elapsed.TotalSeconds));
counter = (counter >= 39) ? 0 : counter + 1;
double tempProgress = Helper.GetTwoDigits(totalBytesRead * 1d / contentLength * 100);
if (progress != tempProgress)
{
progress = tempProgress;
aop.Post(new SendOrPostCallback(delegate
{
if (DownloadPartProgressChanged != null)
DownloadPartProgressChanged(this, EventArgs.Empty);
}), null);
}
if (stop || (rangeAllowed && totalBytesRead == to - from + 1))
{
break;
}
}
#endregion
#region Close Resources
file.Close();
resp.Close();
tempStream.Close();
req.Abort();
resp.Dispose();
stp.Stop();
#endregion
Debug.WriteLine("Threads' exit");
}
在这段代码中,每个下载线程都必须执行最后一行的Debug.WriteLine代码,但有些线程不会执行它。输出为每个线程显示 The thread 0x... has exited with code 259 (0x103).
,但不会为每个线程写入 Threads' exit
。
The output:
Download status
如您所见,部分下载线程停止并直接退出。这个问题是什么原因?
更新:
Thread creation:
public void Start()
{
Task th = new Task(() =>
{
createFirstPartitions();
});
th.Start();
}
void createFirstPartitions()
{
size = Helper.GetContentLength(url, ref rangeAllowed, ref url);
for (int i = 0; i < numberOfParts; i++)
{
PartialDownloader temp = createNewPD(i, numberOfParts, size);
temp.DownloadPartProgressChanged += temp_DownloadPartProgressChanged;
temp.DownloadPartCompleted += temp_DownloadPartCompleted;
pdlist.Add(temp);
temp.Start();
totalPartition++;
}
}
PartialDownloader createNewPD(int order, int parts, long contentLength)
{
long division = contentLength / parts;
long remaining = contentLength % parts;
long start = division * order;
long end = start + division - 1;
end += (order == parts - 1) ? remaining : 0;
return new PartialDownloader(url, tempDirectory,
Guid.NewGuid().ToString(), start, end, true);
}
我找到了我的问题的简单答案。解决方案是使用 HttpWebRequest.ReadWriteTimeout
。默认情况下,它的值为 5 分钟。将其设置为可接受的时间是一个很好的解决方案。
发送请求时添加req.ReadWriteTimeout = 5000
。
然后把代码部分改成这样:
try
{
while ((bytesRead = tempStream.Read(buffer, 0, buffer.Length)) > 0)
{
//....
file.Write(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
}
}
catch
{
//Refresh the connection
}
我有一个项目要通过 Http 使用多线程下载。它会部分下载内容。
对于某些网址和下载速度较慢的情况,部分下载线程在while循环中等待时间过长而没有获取到数据,几次后线程直接退出而没有执行while循环后的代码。我不明白怎么可能。
My code:
void DownloadProcedure()
{
file = new FileStream(this.FullPath,
FileMode.Create, FileAccess.ReadWrite);
#region Request-Response
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12
| SecurityProtocolType.Ssl3;
HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest;
req.Accept = "*/*";
req.Timeout = 3000;
req.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
req.AllowAutoRedirect = true;
req.MaximumAutomaticRedirections = 5;
req.ServicePoint.ConnectionLimit += 2;
req.ServicePoint.Expect100Continue = true;
req.ProtocolVersion = HttpVersion.Version10;
if (rangeAllowed)
req.AddRange(from, to);
resp = req.GetResponse() as HttpWebResponse;
#endregion
#region Some Stuff
contentLength = resp.ContentLength;
if (rangeAllowed && contentLength != to - from + 1)
throw new Exception("Incorrect response content");
tempStream = resp.GetResponseStream();
int bytesRead = 0;
byte[] buffer = new byte[4096];
stp.Start();
#endregion
#region Procedure Loop
while ((bytesRead = tempStream.Read(buffer, 0, buffer.Length)) > 0)
{
while (wait) ;
if (totalBytesRead + bytesRead > contentLength)
bytesRead = (int)(contentLength - totalBytesRead);
file.Write(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
last40Speed[counter] = (int)(totalBytesRead / Math.Ceiling(stp.Elapsed.TotalSeconds));
counter = (counter >= 39) ? 0 : counter + 1;
double tempProgress = Helper.GetTwoDigits(totalBytesRead * 1d / contentLength * 100);
if (progress != tempProgress)
{
progress = tempProgress;
aop.Post(new SendOrPostCallback(delegate
{
if (DownloadPartProgressChanged != null)
DownloadPartProgressChanged(this, EventArgs.Empty);
}), null);
}
if (stop || (rangeAllowed && totalBytesRead == to - from + 1))
{
break;
}
}
#endregion
#region Close Resources
file.Close();
resp.Close();
tempStream.Close();
req.Abort();
resp.Dispose();
stp.Stop();
#endregion
Debug.WriteLine("Threads' exit");
}
在这段代码中,每个下载线程都必须执行最后一行的Debug.WriteLine代码,但有些线程不会执行它。输出为每个线程显示 The thread 0x... has exited with code 259 (0x103).
,但不会为每个线程写入 Threads' exit
。
The output:
Download status
如您所见,部分下载线程停止并直接退出。这个问题是什么原因?
更新:
Thread creation:
public void Start()
{
Task th = new Task(() =>
{
createFirstPartitions();
});
th.Start();
}
void createFirstPartitions()
{
size = Helper.GetContentLength(url, ref rangeAllowed, ref url);
for (int i = 0; i < numberOfParts; i++)
{
PartialDownloader temp = createNewPD(i, numberOfParts, size);
temp.DownloadPartProgressChanged += temp_DownloadPartProgressChanged;
temp.DownloadPartCompleted += temp_DownloadPartCompleted;
pdlist.Add(temp);
temp.Start();
totalPartition++;
}
}
PartialDownloader createNewPD(int order, int parts, long contentLength)
{
long division = contentLength / parts;
long remaining = contentLength % parts;
long start = division * order;
long end = start + division - 1;
end += (order == parts - 1) ? remaining : 0;
return new PartialDownloader(url, tempDirectory,
Guid.NewGuid().ToString(), start, end, true);
}
我找到了我的问题的简单答案。解决方案是使用 HttpWebRequest.ReadWriteTimeout
。默认情况下,它的值为 5 分钟。将其设置为可接受的时间是一个很好的解决方案。
发送请求时添加req.ReadWriteTimeout = 5000
。
然后把代码部分改成这样:
try
{
while ((bytesRead = tempStream.Read(buffer, 0, buffer.Length)) > 0)
{
//....
file.Write(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
}
}
catch
{
//Refresh the connection
}