【发布时间】:2018-08-28 23:10:35
【问题描述】:
我有一段代码每分钟都会访问数据库以检查是否有需要运行的报告,以及是否有运行它。
问题是我对数据库类的对象初始化会造成内存泄漏。如果我每次执行代码时都会查看任务管理器“用户对象”增长 5。
private void ReportRunTimer_Tick(object sender, EventArgs e)
{
DataConnection dataConnection = new DataConnection(); *<-- when executing this line User Object increasing.*
try
{
reportsToRun = dataConnection.GetListOfTheReportForReportRunTick();
if (reportsToRun.Count > 0)
foreach (string report in reportsToRun)
{
logs("Starting Automatic report generatin", "Successful");
Thread TicketReportMethodThread = new Thread(() => GenerateReport(report, 1));
TicketReportMethodThread.Start();
}
dataConnection = null;
} catch (Exception ex)
{
logs("Starting Automatic report generatin failed: " +ex.ToString(), "Error");
}
finally
{
reportsToRun.Clear();
}
}
数据连接类
public List<string> GetListOfTheReportForReportRunTick()
{
List<string> RepoerList = new List<string>();
connString = "Server=xxx;Port=xxx;Database=xxx;Uid=xxx;password=xxxx;SslMode=none";
using (MySqlConnection mySqlConnection = new MySqlConnection(connString))
{
try
{
MySqlCommand mySqlCommand = mySqlConnection.CreateCommand();
mySqlCommand.CommandText = "SELECT reportname FROM reports WHERE nextruntime < NOW()";
mySqlConnection.Open();
MySqlDataReader mySqlDataReader = mySqlCommand.ExecuteReader();
while (mySqlDataReader.Read())
{
RepoerList.Add(mySqlDataReader["reportname"].ToString());
}
}
catch (MySqlException ex)
{
hd.logs("Failed to get reports with reportstorun_tick Error: " + ex.ToString(), "Error");
mySqlConnection.Close();
}
finally
{
mySqlConnection.Close();
mySqlConnection.Dispose();
}
}
return RepoerList;
}
DataConnection dataConnection = new DataConnection(); 用在了其他几个地方,这是唯一引起问题的地方。
如果我用公共列表 GetListOfTheReportForReportRunTick() 中的代码替换私有 void ReportRunTimer_Tick 中的代码,如下所示。问题不再存在,有什么想法吗?
private void ReportRunTimer_Tick(object sender, EventArgs e)
{
List<string> reportsToRun = new List<string>();
try
{
connString = "Server=xxx;Port=xxx;Database=xxx;Uid=xxx;password=xxxx;SslMode=none";
using (MySqlConnection mySqlConnection = new MySqlConnection(connString))
{
try
{
MySqlCommand mySqlCommand = mySqlConnection.CreateCommand();
mySqlCommand.CommandText = "SELECT reportname FROM reports WHERE nextruntime < NOW()";
mySqlConnection.Open();
MySqlDataReader mySqlDataReader = mySqlCommand.ExecuteReader();
while (mySqlDataReader.Read())
{
reportsToRun.Add(mySqlDataReader["reportname"].ToString());
}
if (reportsToRun.Count > 0)
foreach (string report in reportsToRun)
{
logs("Starting Automatic report generatin", "Successful");
Thread TicketReportMethodThread = new Thread(() => GenerateReport(report, 1));
TicketReportMethodThread.Start();
}
}
catch (MySqlException ex)
{
logs("Failed to get reports with reportstorun_tick Error: " + ex.ToString(), "Error");
mySqlConnection.Close();
}
finally
{
mySqlConnection.Close();
mySqlConnection.Dispose();
}
}
}
catch (Exception ex)
{
logs("Starting Automatic report generatin failed: " + ex.ToString(), "Error");
}
finally
{
reportsToRun.Clear();
}
}
问题是由
引起的DataConnection dataConnection = new DataConnection(); *<-- when executing this line User Object increasing.*
reportsToRun = dataConnection.GetListOfTheReportForReportRunTick();
但我不明白为什么。
【问题讨论】:
-
你检查你的日志没有异常发生吗?无论如何,我认为使用
using是一个好主意,这样您就不必担心打开/关闭事情了。 -
还意识到.NET 是一个垃圾收集系统。随着程序运行,内存使用量会增加,直到垃圾收集器启动。此时,您的部分(但不一定是全部)内存将被回收。根据您用于测量“泄漏”的内容,您可能看不到此回收的结果(尽管您明显的内存增长似乎会停止一段时间),如果您想强制垃圾收集作为测试的一部分, 使用
GC.Collect(); -
使用内存分析器。通过任务管理器观察内存使用情况非常具有误导性。
-
mySqlConnection.Close(); mySqlConnection.Dispose();删除那些 - 因为您使用的是using,它们没有做任何事情。 -
我尝试用 public List
GetListOfTheReportForReportRunTick() 中的代码替换私有 void ReportRunTimer_Tick(object sender, EventArgs e) 中的代码,并且“泄漏”停止了。 “用户对象”停止增加。我还注意到,当达到 10,000 时,应用程序总是崩溃。
标签: c# memory-leaks