我的程序下载 5MB 到 100MB 大小的 mp3 文件,内存“泄漏”大小就是下载的大小。单击暂停或取消下载按钮后,内存使用率开始逐渐上升。额外的内存在累积 [filesize] 字节的内存后会自行消失,但我不知道是什么原因造成的,也不知道如何阻止它。
当我跳过/取消下载时,我更改了它检查的状态,以便它退出下载循环并处理来自 HttpWebResponse.GetResponseStream 的流。
然后内存使用量逐渐攀升,例如对于 20MB 的下载,它将攀升 20MB(如果我在下载中途暂停它也没有关系)。它以大约从互联网下载文件所需的速度攀升。当它达到那个数量时,如果下载没有从暂停中恢复,它就会停在那里(如果我取消下载,它会在达到那个点后立即恢复)。当我点击恢复下载时,下载会自动重新启动,一旦它再次开始获取数据,内存使用率立即下降到正常水平。但是,无论哪种方式,在达到最高点之前都不会消除泄漏。
我已经尝试明确处理所有涉及的内容,包括 httpwebresponse,但它没有改变任何东西。似乎有些东西没有被关闭,或者有些东西保留了流的引用,这使得它在被忽略的同时积累和存储东西在内存中......?我不确定该去哪里,还有什么可以给我线索。我希望有一个资源监视器可以告诉我什么样的内容占用了所有内存。感谢您的帮助。
这是我正在使用的代码,尽可能完整,不要太困惑:
public void Download()
{
while( paused )
{
Thread.Sleep( 1000 );
}
if( canceled )
// signal end of download
else
{
// Checking, rechecking, if/else/etc. In short, this:
Enabled = true;
var request = (HttpWebRequest)WebRequest.Create( url );
request.AllowReadStreamBuffering = false;
if( m_bytesCurrentlyDownloaded != 0 )
{
request.Headers["Range"] = string.Format( "bytes={0}-{1}",
m_bytesCurrentlyDownloaded.ToString(),
Filesize - 1 );
}
request.BeginGetResponse( new AsyncCallback( DownloadCallback ), request );
}
}
private void DownloadCallback(IAsyncResult result)
{
var request = (HttpWebRequest)result.AsyncState;
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.EndGetResponse( result );
}
catch( WebException e )
{
response = (HttpWebResponse)e.Response;
}
if( response.StatusCode == HttpStatusCode.OK ||
response.StatusCode == HttpStatusCode.PartialContent )
{
FileMode openMode = (m_bytesCurrentlyDownloaded == 0) ? FileMode.OpenOrCreate : FileMode.Append;
using( var stream = response.GetResponseStream() )
using( var appStorage = IsolatedStorageFile.GetUserStoreForApplication() )
using( var file = new IsolatedStorageFileStream( m_incompleteFilename, openMode, FileAccess.Write, appStorage ) )
{
byte[] chunk = new byte[chunkSize];
int readLength = 0;
do
{
if( paused || canceled )
readLength = 0;
else
{
readLength = stream.Read( chunk, 0, chunkSize );
if( readLength != 0 )
{
file.Write( chunk, 0, readLength );
m_bytesCurrentlyDownloaded = (int)file.Length;
}
}
} while( readLength != 0 );
chunk = null;
}
if( m_bytesCurrentlyDownloaded < Filesize ) // got paused, or connection drop
{
NeedWaitForNetwork(); // waits only if it needs to
Download();
}
else
FinishDownload();
}
}
最佳答案
这有助于我思考:http://msdn.microsoft.com/en-us/magazine/cc163491.aspx对我来说听起来像是堆栈泄漏。线程构成堆栈。总是感觉像是一个不受我控制的线程正在累积所有内存,怀疑可能是某个属于 HttpWebRequest/Response 的线程。
这对我也有帮助:http://www.geekpedia.com/tutorial179_Creating-a-download-manager-in-Csharp.html他正在做类似的事情,当他停止下载时,他会彻底中止他创建的下载线程。那个 .Abort() 调用响了,我查看了 HttpWebRequest.Abort()。
昨天了解 ManualResetEvent 也很有帮助。所以现在我的代码添加了这个:
向我的下载器类添加了一个成员:
private ManualResetEvent downloadBreakoutEvent = new ManualResetEvent( false );
在 Download() 内部,不仅仅是 BeginGetResponse 行,
downloadBreakoutEvent.Reset();
request.BeginGetResponse( new AsyncCallback( DownloadCallback ), request );
downloadBreakoutEvent.WaitOne();
if( canceled || paused )
{
request.Abort();
}
在 DownloadCallback() 的最底部,
downloadBreakoutEvent.Set();
我一遍又一遍地暂停/恢复它,一遍又一遍地取消和重新启动,无论如何,没有内存泄漏!
关于c# - 为什么我的内存使用量在停止下载后激增?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7016647/