C# 为什么在停止下载后我的内存使用量会激增?
我的程序可以下载5MB到100MB大小的mp3文件,内存“泄漏”大小就是下载的大小。单击暂停或取消下载的按钮后,内存使用量开始逐渐增加。这些额外的内存在积累完[filesize]字节的内存后会自动增加,但我不知道是什么导致了它,也不知道如何停止它 当我跳过/取消下载时,我会更改它检查的状态,以便它退出下载循环并从HttpWebResponse.GetResponseStream处理流 然后,内存使用率逐渐上升,例如,对于20MB的下载,它将上升20MB(如果我在下载中途暂停它,这并不重要)。它以大约从互联网下载文件所需的速度攀升。当它达到这个数量时,如果下载没有从暂停中恢复(如果我取消了下载,它会在到达该点后立即返回)。当我点击下载上的resume时,下载会自动重新启动,一旦它再次开始获取数据,内存使用就会立即下降到正常水平。然而,无论哪种方式,它都不会消除泄漏,直到它达到最高点 我已经尝试过明确地处理所有相关的事情,包括httpwebresponse,但它没有改变任何事情。似乎有什么东西没有被关闭,或者有什么东西保留了一个流的引用,这使得它在被忽略时积累并存储在内存中。。?我不知道该怎么做,还有什么能给我线索。我希望有一个资源监视器能告诉我什么样的内容占用了所有的内存。感谢您的帮助 下面是我正在使用的代码,尽可能完整地保存它,而不会有太多混乱:C# 为什么在停止下载后我的内存使用量会激增?,c#,windows-phone-7,memory-management,httpwebrequest,C#,Windows Phone 7,Memory Management,Httpwebrequest,我的程序可以下载5MB到100MB大小的mp3文件,内存“泄漏”大小就是下载的大小。单击暂停或取消下载的按钮后,内存使用量开始逐渐增加。这些额外的内存在积累完[filesize]字节的内存后会自动增加,但我不知道是什么导致了它,也不知道如何停止它 当我跳过/取消下载时,我会更改它检查的状态,以便它退出下载循环并从HttpWebResponse.GetResponseStream处理流 然后,内存使用率逐渐上升,例如,对于20MB的下载,它将上升20MB(如果我在下载中途暂停它,这并不重要)。它以
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();
}
}
publicsvoid下载()
{
while(暂停)
{
睡眠(1000);
}
如果(取消)
//下载结束信号
其他的
{
//检查、重新检查、if/else/等简言之,这:
启用=真;
var request=(HttpWebRequest)WebRequest.Create(url);
request.AllowReadStreamBuffering=false;
如果(m_字节当前下载!=0)
{
request.Headers[“Range”]=string.Format(“bytes={0}-{1}”,
m_bytesCurrentlyDownloaded.ToString(),
文件大小-1);
}
BeginGetResponse(新的AsyncCallback(DownloadCallback),request);
}
}
私有void下载回调(IAsyncResult结果)
{
var request=(HttpWebRequest)result.AsyncState;
HttpWebResponse;
尝试
{
response=(HttpWebResponse)request.EndGetResponse(result);
}
捕获(WebE例外)
{
响应=(HttpWebResponse)e.response;
}
如果(response.StatusCode==HttpStatusCode.OK||
response.StatusCode==HttpStatusCode.PartialContent)
{
FileMode openMode=(m_bytesCurrentlyDownloaded==0)?FileMode.openor创建:FileMode.Append;
使用(var stream=response.GetResponseStream())
使用(var appStorage=IsolatedStorageFile.GetUserStoreForApplication())
使用(var file=new-IsolatedStorageFileStream(m_incompleteFilename,openMode,FileAccess.Write,appStorage))
{
byte[]chunk=新字节[chunkSize];
int readLength=0;
做
{
如果(暂停| |取消)
readLength=0;
其他的
{
readLength=stream.Read(chunk,0,chunkSize);
if(readLength!=0)
{
Write(chunk,0,readLength);
m_bytesCurrentlyDownloaded=(int)file.Length;
}
}
}while(readLength!=0);
chunk=null;
}
如果(m_bytesCurrentlyDownloaded
这让我想起了这件事:对我来说,这听起来像是一个堆栈泄漏。线成堆。总是感觉像是一个我无法控制的线程,正在积累所有的内存,怀疑可能是属于HttpWebRequest/Response的某个线程
这对我也有帮助:他正在做一件类似的事情,当他停止下载时,他会直接中止他制作的下载线程。那个.Abort()调用敲响了警钟,我查看了HttpWebRequest.Abort()
了解昨天的活动也有帮助。因此,现在我的代码添加了以下内容:
已将成员添加到我的downloader类:
private ManualResetEvent downloadBreakoutEvent = new ManualResetEvent( false );
在Download()内部,而不仅仅是BeginGetResponse行
downloadBreakoutEvent.Reset();
request.BeginGetResponse( new AsyncCallback( DownloadCallback ), request );
downloadBreakoutEvent.WaitOne();
if( canceled || paused )
{
request.Abort();
}
在DownloadCallback()的最底部
我一次又一次地暂停/恢复,一次又一次地取消并重新启动,不管怎样,没有内存泄漏 不读取bytesToRead,只读取4096字节。这样就无法获得大型阵列。避免使用BinaryReader,这一点都没有帮助。使用自己的4096字节数组直接从响应流读取。这样你就不会不断地创建新的阵列了。谢谢Hans,这样做更有意义。这部分代码是我第一次开始这个项目时保留的(对C#和所有人来说都是新的),我只是复制粘贴了其他人的代码。我将在几分钟内使用重构代码进行编辑,除非反复创建该数组是问题所在……不幸的是,更改并没有解决内存问题。事实上,这让事情变得更糟了——现在它在恢复后并没有造成内存泄漏。我一定是在做一些非常有趣的事情…不管它变得更糟,似乎它无法删除自己,直到加载完20MB或其他什么,我仍然在看着数字在我恢复之后攀升。
downloadBreakoutEvent.Set();