c# - 为什么我的内存使用量在停止下载后激增?

标签 c# windows-phone-7 memory-management httpwebrequest

我的程序下载 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/

相关文章:

c# - WPF:DataGrid 中的字典<int, List<string>>

c# - 在 CommandText 中使用 SQL 语句选择字段,c#

c# - 通过 List 从其下一个外观绑定(bind)中删除以前的 ComboBox SelectedItem

c# - 尝试访问资源时出现 XamlParseException

silverlight - 删除 silverlight 中按下按钮时突出显示的按钮

c# - 使用 RSA-SHA256 签名方法问题对 Xml 文档进行签名

windows-phone-7 - 在第三方应用程序中显示wp7中的系统铃声列表

c - 如果同一个共享库工作正常,为什么静态库会导致对齐问题?

java - Jboss(Java) 进程对驻留内存使用量的逐渐增加

c++ - C++中delete和delete[]的区别