我的记忆在哪里? 重新初始化DataTable
我有1个DataGridView,1个DataTable等应用程序。
我的“执行”方法(已编辑):
private void btnRunSQL_click() { string strConnStr = tbConnStr.Text; // connection string from textbox string strSQL = tbSql.Text; // query from textbox SqlDataAdapter dataAdapter = new SqlDataAdapter(strSQL, strConnStr); SqlCommandBuilder commandBuilder = new SqlCommandBuilder(dataAdapter); // clean memory // dtData DataTable is declared in main form class dtData = new DataTable(); dataAdapter.Fill(dtData); showMemoryUsage(); }
这是我如何检查内存:
public void showMemoryUsage() { Process proc = Process.GetCurrentProcess(); this.Text = "Peak memory: " + proc.PeakWorkingSet64 / 1024 / 1024 + "MB"; Application.DoEvents(); // force form refresh }
当我多次运行此函数时 – 它使用越来越多的内存。 我正在处理非常大的数据集(1000000行),经过几次大的查询,我必须重新启动我的应用程序。
运行1M行查询后,我有内存使用大约900MB,第二次运行1100MB,1300MB等。
我认为重新初始化DataTable会释放我的记忆,但事实并非如此。 所以我重新初始化了BindingSource(与DataGridView连接),但它也没有帮助。 最后,我评论了我的BindingSource和DataGridView。
后来添加:
处置DataAdapter没有帮助。
我删除了DataGridView和绑定源。 没有帮助。
解决方案(我合并了几个答案并创建了测试应用程序而没有泄漏)
using System; using System.Data; using System.Windows.Forms; using System.Data.SqlClient; using System.Diagnostics; // to run this code you need form and controls: // TextBox tbConnStr - textbox with SQL Server connection string // TextBox tbSQL - for SQL query to run/test // TextBox tbLog - for log display // Button btnRunSQL with OnClick event set to proper method // Button btnRunTest with OnClick event set to proper method namespace Test_datatable { public partial class Form1 : Form { DataTable dt; // i need this global public Form1() { InitializeComponent(); } private void btnRunSQL_Click(object sender, EventArgs e) { log("Method starts."); string strConnStr = tbConnStr.Text; string strSQL = tbSQL.Text; using (SqlDataAdapter da = new SqlDataAdapter(strSQL, strConnStr)) { using (SqlCommandBuilder cb = new SqlCommandBuilder(da)) { if (dt != null) { dt.Clear(); dt.Dispose(); log("DataTable cleared and disposed."); } dt = new DataTable(); da.Fill(dt); log("DataTable filled."); } } log("Method ends."); tbLog.Text += Environment.NewLine; } // prints time, string and memory usage on textbox private void log(string text) { tbLog.Text += DateTime.Now.ToString() + " " + text + memory() + Environment.NewLine; Application.DoEvents(); // force form refresh } // returns memory use as string, example: "Memory: 123MB" private string memory() { Process proc = Process.GetCurrentProcess(); return " Peak memory: " + (proc.PeakWorkingSet64 / 1024 / 1024).ToString() + "MB "; } // test method for 10 runs private void btnRunTest_Click(object sender, EventArgs e) { for (int i = 0; i < 10; i++) { btnRunSQL_Click(new object(), new EventArgs()); } } } }
最好的猜测:通过Bindings仍然存在从GUI到旧DataTables的链接。 但实际的代码丢失了。
我在这方面的首选方法:
if (bs != null) bs.Clear(); // most likely solution if (dtData != null) dtData.Clear(); // won't hurt dtData = new DataTable(); bs = new BindingSource();
对于初学者,你应该处置:
private void btnRunSQL_click() { string strConnStr = tbConnStr.Text; // connection string from textbox string strSQL = tbSql.Text; // query from textbox using(SqlDataAdapter dataAdapter = new SqlDataAdapter(strSQL, strConnStr)) { using(SqlCommandBuilder commandBuilder = new SqlCommandBuilder(dataAdapter)) { // clean memory // dtData DataTable and BindingSource bs are declared in main form class dtData = new DataTable(); bs = new BindingSource(); dataAdapter.Fill(dtData); } } }
但我相信至少部分问题包含在您未向我们展示的代码中。
编辑:请告诉我们您如何使用BindingSource。
EDIT2:您正在使用PeakWorkignSet64,您的应用程序是否以64位运行? 如果不是这个属性将不准确。 另外,尝试System.GC.GetTotalMemory(true)
并告诉我们报告的内容。
SqlDataAdapter和SqlCommandBuilder是一次性的,你可以试试这样的东西
private void btnRunSQL_click() { string strConnStr = tbConnStr.Text; // connection string from textbox string strSQL = tbSql.Text; // query from textbox using(var dataAdapter = new SqlDataAdapter(strSQL, strConnStr)) using(var commandBuilder = new SqlCommandBuilder(dataAdapter)) { dtData = new DataTable(); bs = new BindingSource(); dataAdapter.Fill(dtData); } }
我认为这不会解决你的内存问题,但由于SqlDataAdapter和SqlCommandBuilder是一次性的,因此这是一个好主意。
为什么不重新填充旧的dtData
?
通过创建一个新的dtData
实例,旧的将被垃圾收集器刷新一段时间。 您也可以手动调用GC,但如果有更好的解决方案,我不建议使用。
编辑:为了使其更清晰,请尝试使用此function:
上述就是C#学习教程:我的记忆在哪里? 重新初始化DataTable分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
private void btnRunSQL_click() { string strConnStr = tbConnStr.Text; // connection string from textbox string strSQL = tbSql.Text; // query from textbox using(SqlDataAdapter dataAdapter = new SqlDataAdapter(strSQL, strConnStr)) { using(SqlCommandBuilder commandBuilder = new SqlCommandBuilder(dataAdapter)) { // edited after comment of Jon Senchyna dtData.Clear(); dataAdapter.Fill(dtData); } } }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1008059.html