Моя программа загружает mp3-файлы размером от 5 до 100 МБ, а размер утечки памяти равен размеру загрузки. Использование памяти начинает постепенно увеличиваться после того, как я нажимаю кнопку, которая приостанавливает или отменяет загрузку. Эта дополнительная память обнуляется после того, как она заканчивает накапливать [размер файла] байтов памяти, но я не могу понять, что ее вызывает или как ее остановить.
Когда я пропускаю / отменяю загрузку, я изменяю состояние, которое он проверяет, чтобы он выходил из цикла загрузки и удалял поток из HttpWebResponse.GetResponseStream.
Затем использование памяти постепенно возрастает, например, при загрузке в 20 МБ она поднимется до 20 МБ (не имеет значения, если я приостановил ее в середине загрузки). Он поднимается со скоростью, необходимой для загрузки файла из Интернета. Когда он достигает этой суммы, он становится плато, если загрузка не была возобновлена с паузы (если я отменил загрузку, она сразу же возвращается обратно после достижения этой точки). Когда я нажимаю «возобновить» загрузку, загрузка возобновляется, и как только она снова начинает получать данные, использование памяти немедленно падает до нормального уровня. Однако, в любом случае, он не избавится от утечки, пока не достигнет этой верхней точки.
Я пытался явно избавиться от всего, что связано, включая 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();
}
}