c# - 我应该处理局部类变量吗?

标签 c# out-of-memory idisposable

我有一个旧应用程序,有时会出现 OutOfMemory 异常。我正在尝试调试并解决问题。我正在考虑的选项之一是使用 Dispose() 方法。我知道任何实现 IDisposable 接口(interface)的对象都会让我调用它的 Dispose() 方法,但它也有助于释放资源以将类级别变量设置为 ?像ArrayListHashtable

我在互联网上搜索并找到了一些帖子,但对于是否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() 来级联诸如 connectioncmd 之类的东西是合适的,但是......我的另一部分认为更好的方法是不存储它们,即按需获取连接,并将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/

相关文章:

java - 堆栈帧大小是否有上限

java - 重新安装应用程序时内存消耗增加

c# - 通过构造函数链传递 IDisposable 对象

c# - 实现Finalize和Dispose的正确方法(当父类实现IDisposable时)

c# - ASP.NET 按程序集改变每页的信任级别?

c# - 访问项目的版本信息

PHP算法大数组内存问题

c# - 在 C# 中使用 Finalize/Dispose 方法

c# - 当 Http 请求发生实际下载时

c# - Kendo Grid 自定义操作按钮图标