Author: eaglet
Yesterday, I made a small tool to automatically generate the insert statement. Today, the test found that there is a serious problem that memory cannot be released,CodeI have read it several times and have not found any problems. Later. net memory profiler tracking (for the tracking method, see. net memory profiler tracking. NET application memory usage-Basic Application) found thousands of datarow not released, and finally located as datatable. newrow.
Let's take a look at the problematic code.
PublicDatarow getnextrow ()
{
If(_ Datareader. Read ())
{
Datarow ROW = _ schematable. newrow ();
Foreach(Datacolumn colIn_ Schematable. columns)
{
Row [col. columnname] = _ datareader [col. columnname];
}
ReturnRow;
}
Else
{
Return Null;
}
}
This Code uses the sqldatareader object _ datareader to obtain a row of data. _ Schematable is a able object. This datatable object has no records and only stores the table schema. At first glance, it seems that there is no problem, _ schematable. newrow () generates a new row based on the column information of _ schematable, but this new row does not call _ schematable. rows. the add method is added to the _ schematable table. It is generally considered that the newly generated datarow will be automatically recycled after use, but this is not the case as long as _ schematable is not released, _ schematable. all datarow generated by newrow cannot be released.
I searched the internet and found a renxiong and I encountered the same problem: Table newrow () causes memory leak
The adopted solution is as follows:
Datatable. newrow () adds the created row to the datatable's recordmanager. I am not entirely sure why this happens, but this is why it is not freed by the GC.
It appears that there are only two ways to get rid of the datarow:
- Add it to the table, then delete it.
- Call datatable. Clear ().
That is to say, the datarow object created by the able. newrow method will be added to the recordmanager of the datatable. We can release it using the following two methods:
1. Add this row to the datatable using the datatable. Rows. Add method, and then delete it using the datatable. Rows. Remove Method.
2. Call datatable. Clear () to release the SDK.
Since data tables in my application only store schema information and are always empty tables, I use 2nd methods. After the _ schematable. Clear () clause is added, the memory leakage problem is solved.
The corrected code is as follows:
PublicDatarow getnextrow ()
{
If(_ Datareader. Read ())
{
Datarow ROW = _ schematable. newrow ();
Foreach(Datacolumn colIn_ Schematable. columns)
{
Row [col. columnname] = _ datareader [col. columnname];
}
_ Schematable. Clear ();
ReturnRow;
}
Else
{
Return Null;
}
}
Sorry, the above Code still has a problem, _ schematable. after clear (), the data in datarow is cleared, and the new datarow must be called before _ schematable. this is correct.
Note:
1. Memory leakage is used in the original question of this Article. Many people think this word is improperly used. Yes. Strictly speaking, the problem here is not memory leakage, but memory cannot be released.
2. The problem in this article is caused by the mistake of using ado.net, which is relatively concealed. I wrote it to remind you not to make similar mistakes in the future. This is not a. NET Framework Design issue.