我正在努力编写自己的FTPDownload类,并且在更改了一些我试图解决的问题后遇到了一个问题。
我将在下面粘贴的代码有效地启动下载并运行一段时间,在"main"循环的每次迭代中拉取完整的数据数组。我可以肯定的是,对于小文件(例如html中的会议议程)可以快速且似乎完全复制 - 但是有些东西仍然很不对劲。
在我们说话的时候,我正在下载一个 1.05 GB 的文件,我的下载状态控件显示我 325 Megs 完整 - 我可以证明这样一个事实,即已经通过流收集了这么多数据,但是,这就是事情变得奇怪的地方......到目前为止,我的输出文件中只写入了 548 KB。
以下方法是收集、计数和写入数据 - 在我最近的更改之前,它的性能相当不错,除了一些性能问题,我打算通过将其转换为另一系列类的扩展来解决。
class DownloadThread : StreamReader
{
protected override void Cycle()
{
if (this.IsComplete)
{
this.FireEvent("OnComplete", new Event(this, "DownloadThread has confirmed completion of the targetted download."));
this.Stop();
return;
}
else if ((this._InputSource = this.GetResponseStream(this.RemotePath)) == null)
{
this.FireEvent("OnException",new Event(this,"DownloadThread could not execute. A Response Stream could not be retrieved from the Input Source '" + this.RemotePath + "'."));
this.Stop();
return;
}
else
{
try
{
this._StartTime = DateTime.Now;
Byte[] Bytes = new Byte[4096];
while ((this.BytesLastRead = this.Read(Bytes, 0, 4096)) > 0)
{
this.LocalStream.Write(Bytes, 0, DataMetrics.Length(Bytes));
this.LocalStream.Flush();
this.BytesSinceLast += this.BytesLastRead;
this.TotalRead += this.BytesLastRead;
this.TriggerProgress();
continue;
}
return;
}
catch (Exception e)
{
this.FireEvent("OnException", new Event(this, "An exception was encountered while reading data for the download." + Environment.NewLine + e.Message + Environment.NewLine + e.StackTrace));
return;
}
}
}
protected override Stream GetResponseStream(string RemotePath)
{
this.Request = (FtpWebRequest)FtpWebRequest.Create(this.RemotePath);
if (this.Credentials != null)
this.Request.Credentials = this.Credentials;
this.Response = (FtpWebResponse)this.Request.GetResponse();
Stream ResponseStream = this.Response.GetResponseStream();
return ResponseStream;
}
}
在任何人得出结论之前,需要注意的是,这个"循环"方法在它自己的线程中的循环内自动运行;并且每隔"线程延迟"毫秒就会重复一次(假设它返回)。
此类中的"LocalStream"变量如下所示:
protected Stream _LocalStream = null;
protected Stream LocalStream
{
get
{
if (this.LocalFile == null)
return null;
else if (this._LocalStream == null)
{
if (!this.LocalDirectory.Exists)
this.LocalDirectory.Create();
this._LocalStream = this.LocalFile.OpenWrite();
return this.LocalStream;
}
else
return this._LocalStream;
}
}
我已经考虑过这可能会导致一些冲突 - 并确保一些线程安全在我的待办事项列表中,但目前我在这个领域没有遇到任何问题 - 我只是假设有人可能想看一眼。
根据"下载线程.阅读"方法 - 因为我相信有人会好奇......这是从我自己的"流阅读器"类继承而来的;再次继承自我的"输入阅读器"类。附属字段包括如下。
protected Object _InputSource = null;
public Object InputSource
{
get
{
return this._InputSource;
}
}
public Stream InputStream
{
get
{
if (this.InputSource == null)
return null;
else
{
try
{
return (Stream)this.InputSource;
}
catch (Exception)
{
return null;
}
}
}
}
public override double Read(byte[] buffer, int offset, int count)
{
try
{
return this.InputStream.Read(buffer, offset, count);
}
catch (Exception e)
{
this.Stop();
this.FireEvent("OnException", new Events.Event(this, "An exception was encountered while reading from the InputStream." + Environment.NewLine + e.Message + Environment.NewLine + e.StackTrace));
return 0;
}
}
现在 - 重申 - 我在这里的问题是,由于某种原因,我收到的数据没有被正确推送到文件中。当我完成输入时,我即将完成 ~1 GB 下载,到目前为止没有抛出任何异常,并且流没有"分崩离析" - 但我的输出文件只有 17 兆。
再等 30 秒让此下载完成后,我的 1.05 gig文件变成了 18 meg 文件;但我看不出为什么上面的代码不应该正确处理这个问题。
任何人的建议都会很棒。
问题可能出在这一行代码中:
this.LocalStream.Write(Bytes, 0, DataMetrics.Length(Bytes));
我假设您的DataMetrics.Length()
方法返回错误的字节数,因此我建议您尝试:
this.LocalStream.Write(Bytes, 0, this.BytesLastRead);
相反。
值得注意的是 - 在任何人得出结论之前 - 这是 "循环"方法在循环内自动运行 线;并且将每"线程延迟"毫秒重复一次(假设它 返回 )。
我的第一个猜测是操作系统正在丢弃网卡上的数据,因为它没有主动取消排队,这就是为什么你会得到 17mb 而不是 1gb。