我有一个旧应用程序,有时会出现 OutOfMemory
异常。我正在尝试调试并解决问题。我正在考虑的选项之一是使用 Dispose()
方法。我知道任何实现 IDisposable 接口(interface)的对象都会让我调用它的 Dispose() 方法,但它也有助于释放资源以将类级别变量设置为 空
?像ArrayList
或Hashtable
?
我在互联网上搜索并找到了一些帖子,但对于是否null
对象有点困惑。
我正在尝试的代码
public class RepET : base_entitlement, IDisposable
{
#region Public Member Variables
public const int ENTITLEMENT_TYPE = 7;
public string table = "acc_rep";
public ArrayList country_list;
public Hashtable data;
public ArrayList survey_dates;
public ArrayList city_list;
public Dictionary<string, Dictionary<string, string>> cityData;
public Dictionary<string, Dictionary<string, string>> reportCity_list;
public RepET(string entId)
{
if (id != "0")
{
id = entId;
// if we cant load the metadata then load the full records & build the metadata
if (!LoadFromMetaDb(id, ENTITLEMENT_TYPE))
{
if (this.load_entitlements())
{
serialize_to_metadb(this, ENTITLEMENT_TYPE);
}
}
}
}
#endregion
public bool load_entitlements()
{
// loads this entitlement from the metadata
this.data = new Hashtable();
this.survey_dates = new ArrayList();
this.city_list = new ArrayList();
//SqlQueries.ProcessingStarted(id);
var sdates = SqlQueries.GetNewestSurveyByET(this.table, id, "acc_rep");
if (sdates.Count == 0) return false;
else
{
//delete ent 4 if already exist as its regenerated here
check_EntFile_Created(id, Constants.ENTITLEMENT_TYPE_RP.ToString(), true);
o_report_entitlements = new report_entitlements(id);
reportCity_list = new Dictionary<string, Dictionary<string, string>>();
foreach (string sd in sdates)
{
ent_by_survey_date(sd.Trim(), true);
this.survey_dates.Add(sd.Trim());
}
o_report_entitlements.serialize_to_metadb(o_report_entitlements, Constants.ENTITLEMENT_TYPE_RP);
return true;
}
}
public bool ent_by_survey_date(string survey_date, bool modify_report_entitlements = false)
{
//if (modify_report_entitlements) {
// ArrayList countryArray;
//}
var dt = SqlQueries.Ent_by_survey_date(table, id, survey_date, "acc");
if (dt.Rows.Count == 0)
{
return false;
}
else
{
country_list = new ArrayList();
city_list = new ArrayList();
Dictionary<string, ArrayList> countryCodes = new Dictionary<string, ArrayList>();
foreach (DataRow row in dt.Rows)
{
string current_city_code = row["city_code"].ToString().Trim();
string current_report_type = row["report_type"].ToString().Trim();
if (!string.IsNullOrEmpty(current_city_code))
{
Dictionary<string, string> currentCityReportList = new Dictionary<string, string>();
if (!reportCity_list.ContainsKey(survey_date))
{
reportCity_list[survey_date] = new Dictionary<string, string>();
reportCity_list[survey_date].Add(current_city_code, current_report_type);
}
else if (reportCity_list != null && reportCity_list.ContainsKey(survey_date) && !reportCity_list[survey_date].ContainsKey(current_city_code))
{
reportCity_list[survey_date].Add(current_city_code, current_report_type);
}
if (modify_report_entitlements)
{
string current_country_code = get_country_code_by_city(current_city_code);
if (!country_list.Contains(current_country_code))
{
country_list.Add(current_country_code);
foreach (var item in ((System.Reflection.TypeInfo)(o_report_entitlements.GetType())).DeclaredFields)
{
if (item.Name == "data")
{
Hashtable tempObj = (Hashtable)item.GetValue(o_report_entitlements);
if (tempObj != null)
{
countryCodes = (Dictionary<string, ArrayList>)tempObj[id];
if (countryCodes != null && !countryCodes.ContainsKey(current_country_code))
this.o_report_entitlements.add_to_array(current_country_code, "ACC", "", ref countryCodes);
else if (countryCodes != null && countryCodes.ContainsKey(current_country_code) && !countryCodes[current_country_code].Contains("ACC"))
this.o_report_entitlements.add_to_array(current_country_code, "ACC", "", ref countryCodes);
else if (!countryCodes.ContainsKey(current_country_code))
this.o_report_entitlements.add_to_array(current_country_code, "ACC", "", ref countryCodes);
}
else
{
if (countryCodes == null)
countryCodes = new Dictionary<string, ArrayList>();
this.o_report_entitlements.add_to_array(current_country_code, "ACC", "", ref countryCodes);
}
}
}
}
}
if (!city_list.Contains(current_city_code))
{
city_list.Add(current_city_code);
}
if (!currentCityReportList.ContainsKey(current_city_code))
{
currentCityReportList.Add(current_city_code, current_report_type);
}
if (!data.ContainsKey(survey_date))
{
data[survey_date] = new Hashtable();
}
switch ((((Hashtable)this.data[survey_date])).GetType() == typeof(Dictionary<string, string>))
{
case true:
break;
case false:
default:
((Hashtable)this.data[survey_date])[current_city_code] = new Dictionary<string, string>();
(((Dictionary<string, string>)((Hashtable)this.data[survey_date])[current_city_code])["city_code"]) = current_city_code;
//(((Dictionary<string, string>)((Hashtable)this.data[survey_date])[current_city_code])["city_code"])
//(((Dictionary<string, ArrayList>)((Hashtable)this.data[survey_date])[current_city_code])["report_type"]) = new ArrayList();
(((Dictionary<string, string>)((Hashtable)this.data[survey_date])[current_city_code])["report_type"]) = current_report_type;
//((Dictionary<string, string>)((Hashtable)this.data[survey_date])[current_city_code])["report_type"] = current_report_type;
break;
}
}
}
}
return true;
}
public string get_country_code_by_city(string city_code)
{
load_city_list();
string returnItem = null;
foreach (var item in cityData)
{
Dictionary<string, string> subItem = item.Value;
if (subItem.ContainsKey(city_code))
{
returnItem += item.Key;
}
}
return returnItem;
}
public bool load_city_list()
{
if (GlobalObjs.dtCityList.Rows.Count == 0)
GlobalObjs.dtCityList = SqlQueries.LoadCityList();
//var dt = SqlQueries.LoadCityList();
if (GlobalObjs.dtCityList.Rows.Count == 0)
{
return false;
}
Dictionary<string, string> cityList = new Dictionary<string, string>();
cityData = new Dictionary<string, Dictionary<string, string>>();
foreach (DataRow row in GlobalObjs.dtCityList.Rows)
{
string Country_Code = row["Country_Code"].ToString().Trim();
string City_Code = row["City_Code"].ToString().Trim();
string City_Name = row["Name"].ToString().Trim();
if (!cityData.ContainsKey(Country_Code))
{
cityData.Add(Country_Code, new Dictionary<string, string>());
}
Dictionary<string, string> tempList = cityData[Country_Code];
if (!tempList.ContainsKey(City_Code))
{
tempList.Add(City_Code, City_Name);
//cityList.Add(City_Code, City_Name);
cityData[Country_Code] = tempList;
}
}
return true;
}
// Flag: Has Dispose already been called?
bool disposed = false;
// Protected implementation of Dispose pattern.
protected void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
country_list = null;
data = null;
survey_dates = null;
city_list = null;
cityData = null;
reportCity_list = null;
}
disposed = true;
}
public void Dispose()
{
Dispose(true);
}
}
这对内存异常有帮助吗?
最佳答案
将字段设置为 null
唯一会对垃圾收集产生影响的情况是,如果您仍然以某种方式让 RepET
实例可访问,在这种情况下真正的解决方案是:确保 RepET 实例不再可达!将字段设置为 null
掩盖了真正的问题。
使用 Dispose()
来级联诸如 connection
和 cmd
之类的东西是合适的,但是......我的另一部分认为更好的方法是不存储它们,即按需获取连接,并将cmd
完全保留在使用位置的本地;像这样:
using (var conn = SomeHelper.CreateConnection())
{
// your "cmd" code in here, via "using" - or
// perhaps via "Dapper" and let it worry about that
}
但是,真正的技巧是找到实例的持有者,如果这就是真正的问题。没有上下文很难评论,但是:事件和静态缓存是开始寻找的好地方。
关于c# - 我应该处理局部类变量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60504165/