为什么在C#中将文件写入磁盘后不释放内存

Cla*_*aro 0 .net c# sockets optimization network-programming

我有一个复杂的算法,它从套接字连接接收数据,转换数据并尽快将其存储在HD上.由于这一事实,我不希望处理速度减慢的数据是通过使用不同的线程.数据存储算法类似于这种结构.它基本上将XML保存在磁盘上.

Begin Thread
 beginthread:

 XmlTextWriter xmltextWriter;
 Save Xml file 1
 xmltextWrite.close();

 XmlTextWriter xmltextWriter;
 Save Xml file 2
 xmltextWrite.close();

 goto beginthread:
End Thread
Run Code Online (Sandbox Code Playgroud)

它工作正常,但如果我看一下任务管理器,我可以注意到我的程序消耗的内存量随着时间的推移而迅速增加(工作1小时后为500mb).这可能是合理的,因为线程没有进入的数据那么快,.NET框架为我存储临时内存.但我不明白为什么如果传入的套接字连接将停止,即使几分钟后线程继续工作......任务管理器继续显示500Mb的内存..为什么内存没有被重新启动?!XmlTextWriter对象是一个局部变量,每次都会关闭.

按要求..这是代码的一部分

     beginthread:
        if (sleeptime < 1000) sleeptime += 2;

        try
        {

            while (hashBeginConn.Count > 0)
            {
                sleeptime = 0;

                int connToApply = hashBeginConn[0];

                if (olddate.ToShortDateString() != ListsockConnections[connToApply].beginDate.ToShortDateString())
                {
                    JoinDataFromTempFile(ListsockConnections[connToApply].beginDate.Date.Subtract(olddate.Date).Days, false, d);
                    olddate = ListsockConnections[connToApply].beginDate.Date;
                }

                if (tocreate)
                {
                    // XML Serialization
                    XmlTextWriter xmltextWriter;

                    Encoding enc = null;
                    if (ListsockConnections[connToApply].ENCfromCode) enc = Encoding.GetEncoding(ListsockConnections[connToApply].codepage);
                    if (ListsockConnections[connToApply].ENCDefault) enc = Encoding.Default;
                    if (ListsockConnections[connToApply].ENCfromText) enc = Encoding.GetEncoding(ListsockConnections[connToApply].codename);
                    if (enc == null) { enc = null; }

                    // xmltextWriter = new XmlTextWriter(folderPath + "\\" + cacheFileName, enc);
                    xmltextWriter = new XmlTextWriter(DataPath + "\\_temp.xml", enc);
                    xmltextWriter.Formatting = Formatting.Indented;

                    // Start document
                    // xmltextWriter.WriteStartDocument();
                    xmltextWriter.WriteStartElement("ConnectionList");
                    xmltextWriter.WriteStartElement("connection");

                    xmltextWriter.WriteStartElement("ConnectionCounter");
                    xmltextWriter.WriteValue(ListsockConnections[connToApply].ConnectionCounter.ToString());
                    xmltextWriter.WriteEndElement();

                    xmltextWriter.WriteStartElement("IDConnection");
                    xmltextWriter.WriteValue(ListsockConnections[connToApply].IDConnection.ToString());
                    xmltextWriter.WriteEndElement();

                    xmltextWriter.WriteStartElement("Parsed");
                    xmltextWriter.WriteValue("false");
                    xmltextWriter.WriteEndElement();

                    xmltextWriter.WriteStartElement("connType");
                    xmltextWriter.WriteValue("TCP/IP");
                    xmltextWriter.WriteEndElement();

                    xmltextWriter.WriteStartElement("beginConn");
                    xmltextWriter.WriteValue(ListsockConnections[connToApply].beginDate.ToString());
                    xmltextWriter.WriteEndElement();

                    xmltextWriter.WriteStartElement("remoteAddressFamily");
                    xmltextWriter.WriteValue(ListsockConnections[connToApply].remoteAdressFamily);
                    xmltextWriter.WriteEndElement();

                    xmltextWriter.WriteStartElement("remoteIP");
                    xmltextWriter.WriteValue(ListsockConnections[connToApply].remoteIP);
                    xmltextWriter.WriteEndElement();

                    xmltextWriter.WriteStartElement("localIP");
                    xmltextWriter.WriteValue(ListsockConnections[connToApply].localIP);
                    xmltextWriter.WriteEndElement();

                    xmltextWriter.WriteStartElement("remoteport");
                    xmltextWriter.WriteValue(ListsockConnections[connToApply].remoteport.ToString());
                    xmltextWriter.WriteEndElement();

                    xmltextWriter.WriteStartElement("localport");
                    xmltextWriter.WriteValue(ListsockConnections[connToApply].localport.ToString());
                    xmltextWriter.WriteEndElement();

                    xmltextWriter.WriteStartElement("dataEncoding");
                    if (ListsockConnections[connToApply].codepage != 0 || ListsockConnections[connToApply].codename != "")
                    {
                        if (ListsockConnections[0].codepage != 0)
                        { xmltextWriter.WriteValue(ListsockConnections[connToApply].codepage.ToString()); }
                        else
                        { xmltextWriter.WriteValue(ListsockConnections[connToApply].codename.ToString()); }
                    }
                    else
                    { xmltextWriter.WriteValue("NONE"); }
                    xmltextWriter.WriteEndElement();

                    xmltextWriter.WriteEndElement();
                    xmltextWriter.WriteEndElement();
                    xmltextWriter.Flush();
                    xmltextWriter.Close();

                    tocreate = false;
                }
                else
                {
                    FileInfo fi;
                    FileStream fstream;

                    //fi = new FileInfo(folderPath + "\\" + cacheFileName);
                    fi = new FileInfo(DataPath + "\\_temp.xml");
                    fstream = fi.OpenWrite();

                    XmlTextWriter xmltextWriter;

                    Encoding enc = null;
                    if (ListsockConnections[connToApply].ENCfromCode) enc = Encoding.GetEncoding(ListsockConnections[connToApply].codepage);
                    if (ListsockConnections[connToApply].ENCDefault) enc = Encoding.Default;
                    if (ListsockConnections[connToApply].ENCfromText) enc = Encoding.GetEncoding(ListsockConnections[connToApply].codename);
                    if (enc == null) { enc = null; }

                    xmltextWriter = new XmlTextWriter(fstream, enc);

                    xmltextWriter.Formatting = Formatting.Indented;

                    fstream.Position = fstream.Length - 17;

                    xmltextWriter.WriteRaw("  <connection>" + Environment.NewLine);

                    xmltextWriter.WriteRaw("     <ConnectionCounter>");
                    xmltextWriter.WriteValue(ListsockConnections[connToApply].ConnectionCounter.ToString());
                    xmltextWriter.WriteRaw("</ConnectionCounter>" + Environment.NewLine);

                    xmltextWriter.WriteRaw("     <IDConnection>");
                    xmltextWriter.WriteValue(ListsockConnections[connToApply].IDConnection.ToString());
                    xmltextWriter.WriteRaw("</IDConnection>" + Environment.NewLine);

                    xmltextWriter.WriteRaw("     <Parsed>");
                    xmltextWriter.WriteValue("false");
                    xmltextWriter.WriteRaw("</Parsed>" + Environment.NewLine);

                    xmltextWriter.WriteRaw("     <connType>");
                    xmltextWriter.WriteValue("TCP/IP");
                    xmltextWriter.WriteRaw("</connType>" + Environment.NewLine);

                    xmltextWriter.WriteRaw("     <beginConn>");
                    xmltextWriter.WriteValue(ListsockConnections[connToApply].beginDate.ToString());
                    xmltextWriter.WriteRaw("</beginConn>" + Environment.NewLine);

                    xmltextWriter.WriteRaw("     <remoteAddressFamily>");
                    xmltextWriter.WriteValue(ListsockConnections[connToApply].remoteAdressFamily);
                    xmltextWriter.WriteRaw("</remoteAddressFamily>" + Environment.NewLine);

                    xmltextWriter.WriteRaw("     <remoteIP>");
                    xmltextWriter.WriteValue(ListsockConnections[connToApply].remoteIP);
                    xmltextWriter.WriteRaw("</remoteIP>" + Environment.NewLine);

                    xmltextWriter.WriteRaw("     <localIP>");
                    xmltextWriter.WriteValue(ListsockConnections[connToApply].localIP);
                    xmltextWriter.WriteRaw("</localIP>" + Environment.NewLine);

                    xmltextWriter.WriteRaw("     <remotePort>");
                    xmltextWriter.WriteValue(ListsockConnections[connToApply].remoteport.ToString());
                    xmltextWriter.WriteRaw("</remotePort>" + Environment.NewLine);

                    xmltextWriter.WriteRaw("     <localport>");
                    xmltextWriter.WriteValue(ListsockConnections[connToApply].localport.ToString());
                    xmltextWriter.WriteRaw("</localport>" + Environment.NewLine);

                    xmltextWriter.WriteRaw("     <dataEncoding>");
                    if (ListsockConnections[connToApply].codepage != 0 || ListsockConnections[connToApply].codename != "")
                    {
                        if (ListsockConnections[connToApply].codepage != 0)
                        {
                            xmltextWriter.WriteValue(ListsockConnections[connToApply].codepage.ToString());
                        }
                        else
                        {
                            xmltextWriter.WriteValue(ListsockConnections[connToApply].codename.ToString());
                        }
                    }
                    else
                    {
                        xmltextWriter.WriteValue("NONE");
                    }
                    xmltextWriter.WriteRaw("</dataEncoding>" + Environment.NewLine);

                    xmltextWriter.WriteRaw("  </connection>" + Environment.NewLine);
                    xmltextWriter.WriteRaw("</ConnectionList>");

                    xmltextWriter.Flush();
                    xmltextWriter.Close();
                    fstream.Close();


                    if (fi.Length >= (maxFileTempSize * 1000000))
                    {
                        JoinDataFromTempFile(0, false, enc);
                    }
                }

                lock (lockThis)
                {
                    hashBeginConn.RemoveAt(0);
                }

            }
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 8

许多答案都说你必须打电话给Dispose.虽然这些答案意味着很好,但实际上并没有帮助你.您正在调用Close,而Close和Dispose执行相同的操作.使用"使用"块是一种更好的做法,这样你就可以自动为你调用Dispose,但是你的代码很好.

你问题的真正答案是"不要再担心了".你在错误的层面上考虑这个问题.我假设您正在查看任务管理器中的"工作集"或"私有字节",但您可能无法理解这些实际意味着什么.大多数人没有.这个答案给出了很好的总结:

什么是专用字节,虚拟字节,工作集?

好了,现在您知道"私有字节"是什么,应该更清楚为什么这不是问题.假设您是CLR垃圾收集器.您代表用户分配了一堆内存,并使用它来存储托管对象.垃圾收集器时不时地运行,压缩内存中的对象,并将以前死亡对象以前使用的内存标记为可用.但为什么GC会将所有这些内存块返回给操作系统? GC有证据表明你是那种编写使用那么多内存的程序的人,所以它保留了空页面,以便以后当你再次使用那么多内存时不必再花费再分配它们的费用从现在开始的毫秒数.

所以,不要再担心了.一切都很好.使用5亿字节的内存不是问题.如果开始虚拟内存不足,GC可能会开始解除对未使用页面的拒绝.如果没有 - 如果它不受限制地增长,那么开始担心.

如果您仍然担心,请使用正确的工具."私有字节"很少告诉您程序中内存实际发生的情况.如果您想知道垃圾收集器中发生了什么,那么您需要使用托管内存分析器.它将为您提供确切报告的报告.


Elr*_*ynn 5

你应该打电话xmltextWriter.Dispose().

此外,在垃圾收集器启动之前,内存不会被释放.您通常应该允许这种情况自动发生,但您可以使用静态方法GC.Collect()显式调用它.建议不要明确调用gc.collect.让CLR按照自己的时间表来做.