2

我正在使用 C# 和 OBDC DSN 连接到 Paradox 数据库。如果我打开和关闭每个连接,我似乎正在泄漏内存。

我的代码基本上是:

            csb.Dsn = "DNSName";
            OdbcConnection con = new OdbcConnection(csb.ConnectionString);
            con.Open();

            OdbcCommand comm= new OdbcCommand("SELECT * FROM Tabl", con);
            OdbcDataReader reader= null;
            try
            {
                reader= comm.ExecuteReader();
                for (int count = 0; (count < 5 && reader.Read()); ++count)
                {
                    //Read
                }
            }
            finally
            {
                if (reader!= null)
                {
                    reader.Close();
                    reader.Dispose();
                }
                if (comm!= null)
                {
                    con.Close();
                    con.Dispose();
                    OdbcConnection.ReleaseObjectPool();
                    GC.Collect();
                    comm.Dispose();
                }
            }

有什么想法或建议吗?

更新 1

我将其更改为使用语句,但仍然泄漏。

4

4 回答 4

3
使用 (var connection = new OdbcConnection(csb.ConnectionString))
{
    连接.打开();
    使用 (var command = new OdbcCommand("SELECT * FROM Tabl", connection))
    使用 (var reader = command.ExecuteReader())
    {
        for (var count = 0; (count < 5 && reader.Read()); ++count)
        {
            //读
        }
    }
}
OdbcConnection.ReleaseObjectPool();

上述代码中没有内存泄漏,除非它是在“//Read”执行点创建的。GC.Collect 永远不应该在生产中使用;无论如何,它很可能无济于事,并且实际上可能会阻碍 GC,因为它是自我调整的。使用ANTS Memory Profiler之类的分析器(或免费试用版),看看你的对象上挂着什么。

不要相信 Windows 任务管理器会显示您是否有泄漏。确保为此目的使用分析器。

于 2010-08-06T00:34:15.063 回答
2

尝试将连接、命令和阅读器放在using语句中。

然后OdbcConnection.ReleaseObjectPool(); 在最后调用。

注意:垃圾收集运行可能需要几分钟。为了证明没有泄漏,您可以GC.Collect()连续调用三次 [三次清除所有三代的对象]。

但是不要留下GC.Collect()生产中的代码,因为它可能会对性能造成很大影响。

于 2010-02-18T19:45:51.690 回答
0

尽量避免调用 GC.Collect

除非您 100% 确定自己知道自己在做什么,否则切勿触摸垃圾收集器。永远记住——垃圾收集器比你聪明,它知道运行的最佳时间。

于 2010-08-06T02:40:11.560 回答
0

你是如何发现泄漏的?有时,任务管理器中的内存使用量上升并且没有立即释放可能是由于 GC 没有立即启动,或者您的连接池或句柄尚未在托管环境中释放。我建议您使用 Travis 建议的 ANTS Mem Profiler 之类的内存分析器。您可以获得试用版,否则使用 Microsoft CLRProfiler 的基本版本。

另一个很好的措施是加载进程,使其在分析过程中运行更长时间,这样如果有问题,它就会清楚地显示出来。最简单的方法是在它周围放置一个循环,以便将上面的代码运行 1000 次或更多。您还可以使用性能监视器来监视一些感兴趣的计数器,并查看它们在执行期间如何跟踪。

于 2010-08-06T00:56:30.433 回答