【问题标题】:C# program Out of memoryC#程序内存不足
【发布时间】:2016-06-27 13:40:13
【问题描述】:

我的程序内存不足。我不明白为什么我在“处理”时设置了object = null

foreach (DataRow theRow in thisDataSet.Tables["Collection"].Rows)
{
    LS_BatchAID = Convert.ToString(theRow["BatchAID"]);
    LS_Batch = Convert.ToString(theRow["Batch"]);
    LS_ID = Convert.ToString(theRow["ID"]);
    CL_Batch Batch = new CL_Batch(LS_BatchAID, LS_ID, LS_Batch);
    Batch = null;
}

thisConnection.Close();

我收到此错误:在 mscorlib.dll 中发生 System.OutOfMemoryException' 在运行程序和观察taskmanager的同时,我可以看到内存消耗随着代码的迭代次数线性上升。

我应该如何制作一个不会增加内存消耗/转储的程序?

CL_Batch:

class CL_Batch
    {
        private string BatchAID;
        private string ID;
        private string Batch;
        private string pathPDF;
        private string pathCPR;
        private string pathLog;
        private string DateXMLGenerated;

        private string[] IDType; 
        private string[,] IDTypes;
        private string[] Files;
        private DateTime Dates;
        private byte[] pdfContent;
        private string XMLContent;
        private string[] RefNbr;

        public CL_Batch(string IV_BatchAID, string IV_ID, string IV_Batch)
        {
            this.Dates = DateTime.Now;

            this.DatoXMLGenerated = "" + Dato.Date.Year.ToString() + "-" + BuildNumber(true, 2, Dato.Date.Month.ToString()) + "-" + BuildNumber(true, 2, Dato.Date.Day.ToString()) + "";
            this.BatchAID = IV_BatchAID;
            this.ID = IV_ID;
            this.Batch = IV_Batch;
            this.pathPDF = @"C:\path\TempFiles\path\" + this.ID + ".Pdf";
            this.pathCPR = @"C:\path\TempFiles\";
            this.pathLog = @"C:\path\Log\" + this.Batch + ".txt";

            setRefnbr();

                // Set array with mappings of ID between partners.
                setLegitimationsTyper();

                // ensure log is available ( [NameOfLog] ).
                prepareLog();

                // Find all files for archive.
                getFileNames();

                // Move files C:\path\TempFiles\
                if (this.getFiles() == true)
                {
                    // Create PDF's. 
                    makePDF();

                    // Insert PDF's in database.
                    insertPDF();

                    // Create XML files.
                    makeXML();

                    // Insertt XML in database.
                    insertXML();

                }



        public string getBatchAID()
        {
            return this.BatchAID;
        }

        public string getID()
        {
            return this.ID;
        }

        public string getBatch()
        {
            return this.Batch;
        }

        public string getIDTyper(string IV_Code, bool kode)
        {

            for (int i = 0; i <= this.IDTypes.GetUpperBound(0); i++)
            {
                if (this.IDTypes[i, 0] == IV_Kode)
                {
                    if (Code == true)
                    {
                        return this.LegitimationsTyper[i, 1];
                    }
                    else
                    {
                        return this.LegitimationsTyper[i, 2];
                    }
                }
            }
            return "";
        }
}

/******************************************/

/** 更新 #1 **************************/

很公平!滥用构造函数。我明白了 - 但是: 真正的问题是什么?

如果我按照我已经做的那样做对比这个例子:

CL_Batch Batch = new CL_Batch(LS_BatchAID, LS_ID, LS_Batch);

Batch.setRefnbr();
Batch.setIDTypes();
Batch.prepareLog();
Batch.getFileNames();
Batch.makePDF();
Batch.insertPDF();
Batch.makeXML();
Batch.insertXML();
Batch = null;

那么真正的区别是什么? 如果是用不同的方法来添加几个数字,那么最终会得到相同的指令。

First program:
xor ax, ax
mov ax, 10
add ax, 10

Second program:
xor ax, ax
mov ax, 10
add ax, 10

我认为最终没有区别(我认为我误用了 oop 的概念,但最终产品是相同的 - 我希望)

请就我的错觉给我建议。

提前致谢。 /** 更新 #1 / /******************************************/

【问题讨论】:

  • 什么是 CL_Batch?
  • 将你的 sn-p 降低到 foreach 并不是一种将噪音降到最低的方法 - 如果你只是降低整个班级的噪音并向我们展示这个减少的班级会更好 -你永远不知道它可能不在你的 foreach 循环中
  • CL_Batch的构造函数是什么?为什么你要把你刚刚创建的对象清空?这闻起来像是被滥用的构造函数。
  • 我们仍然缺少相关代码。构造函数正在调用未包含的方法。问题可能是任何事情。但是你不应该在你的构造函数中有“做某事”的行为。很明显,您这样做是因为您正在创建对象然后将其设置为 null,这表明仅创建对象会导致某些事情发生。我们应该创建一个对象,然后对这个对象做一些事情。构造函数本身不应该是类的行为所在。
  • 恕我直言,尝试学习面向对象编程的基础知识。构造函数应该用来构造一个对象,而不是执行各种代码。这不仅会使您创建的对象变得无用,还会使其无法用于其他用例。

标签: c# object out-of-memory


【解决方案1】:

这是在黑暗中刺探,因为我们看不到您的代码。您正在创建 PDF。这通常涉及某种 COM 对象或内存流。也许您用来创建这些 PDF 的任何东西都没有得到处理或清理,因此您创建的每个 PDF 都存放在内存中,直到您用完为止。我会仔细查看您正在使用的任何组件的文档。如果某些东西实现了IDisposable,请确保您正在处理它。

【讨论】:

    【解决方案2】:

    即使我不同意关于糟糕的构造函数代码的建议,但我必须承认它产生了影响,并且在从构造函数中删除代码后代码可以按预期工作。 如果有人对我有很好的解释,那么我想听听。 无论如何我可以给你们(BugFinder, 卡勒姆·林宁顿, 混合剑突, 马诺德斯特拉, 迈克·罗宾逊, 马修·怀特, Scott Hannen)归功于解决方案?

    这是有效的代码:

     foreach (DataRow theRow in thisDataSet.Tables["Collection"].Rows)
     {
      LS_BatchAID = Convert.ToString(theRow["BatchAID"]);
      LS_Batch = Convert.ToString(theRow["Batch"]);
      LS_ID = Convert.ToString(theRow["ID"]);
      CL_Batch Batch = new CL_Batch(LS_BatchAID, LS_ID, LS_Batch);
      Batch.setRefnbr();
      Batch.setIDTypes();
      Batch.prepareLog();
      Batch.getFileNames();
      Batch.makePDF();
      Batch.insertPDF();
      Batch.makeXML();
      Batch.insertXML();
     }
     thisConnection.Close();
    

    【讨论】:

    • 这不是答案。你应该删除它。此外,您仍在数据循环中进行所有这些处理。而且您不需要最后的 Batch = null 行。它只在每次迭代时被实例化一次,无论如何它都会再次被实例化,所以将它设置为 null 是没有意义的。问题在于后续的方法。我不会做你在这里做的事情。我会在这个循环之外的单独循环中进行该处理,但至少现在您可以更好地识别发生内存泄漏的位置,因为您已经打破了一点逻辑。
    • @ManoDestra 感谢您的回复。关于程序,内存消耗按预期上下移动 - 现在。关于您在数据循环中的处理声明。如果不是这样,我该怎么做?提前致谢。请对我温柔一点。我在这里被打了。
    • 两种方法。您在这里完成的方式更好,因为您应该更好地了解内存消耗导致程序崩溃的线路。从那里,您可以深入了解原因。就个人而言,我会将所有这些方法调用(.setRefnbr()、setIDTypes() 等)移至第二个循环。因此,如上所述,循环遍历表的行,但将每个 CL_Batch 添加到 List 中。然后在此循环之后循环遍历该列表并在那里执行方法调用。有意义吗?
    • 我礼貌地不同意,ManoDestra:它“答案”,因为它使主题结束:“这个,记录在案,我是如何修复这个的。”是的,您可以在原始帖子中添加相同的内容。但是,我绝对喜欢看到一个“即将结束”的线程(在任何论坛、任何地方)。它反映:最初的困惑、导致解决方案的讨论、和解决方案。
    • 是的,我仍然希望看到解决方案。我仍然想知道问题出在哪里。并且仍然值得将您的 Connection 实例包装在 using 中,而不是显式关闭它:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-14
    • 2020-12-23
    • 2020-10-17
    • 1970-01-01
    • 1970-01-01
    • 2014-04-27
    相关资源
    最近更新 更多