如何强制释放对象/GC

3

如何强制对象在使用后进行处理以释放内存?另外,如何强制垃圾回收机制进行回收?

这里是我的保存代码。我注意到每次执行此函数时,我的内存消耗都会增加,最终可能会在几次操作后导致内存不足错误。

protected void btnSaveEmptyOC_Click(object sender, EventArgs e)
{


    try
    {

        if (ViewState["ServiceDetailID"].ToString() != null)
        {
            CashExpense tblCashExpenses = new CashExpense();
            Guid CashExpensesID = Guid.NewGuid();

            tblCashExpenses.CashExpensesID = CashExpensesID;


            tblCashExpenses.ServiceDetailsID = new Guid(ViewState["ServiceDetailID"].ToString());

            tblCashExpenses.Description = txtDescriptionEmptyOC.Text;
            tblCashExpenses.Quantity = Decimal.Parse(txtQTYEmptyOC.Text);
            tblCashExpenses.UnitCost = Decimal.Parse(txtUnitCostEmptyOC.Text);
            tblCashExpenses.CreatedBy = User.Identity.Name;
            tblCashExpenses.DateCreated = DateTime.Now;
            tblCashExpenses.CashExpensesTypeID = "OTHER";

            CashExpenses_worker.insert(tblCashExpenses);
            CashExpenses_worker.submit();
            //Clear items after saving
            txtDescriptionEmptyOC.Text = "";
            txtQTYEmptyOC.Text = "";
            txtUnitCostEmptyOC.Text = "";


            ValidationMessage.ShowValidationMessage(MessageCenter.CashExpenseMaintenace.InsertOC2, "SaveEmptyOC", this.Page);
            MyAuditProvider.Insert(this.GetType().ToString(), ViewState["MarginAnalysisID"].ToString(), MessageCenter.Mode.ADD, MessageCenter.CashExpenseMaintenace.InsertOC2, Page.Request, User);
            divOtherCost.Visible = false;
            grd_othercost.Visible = true;
            btnaddothercost.Visible = true;

            tblCashExpenses = null;
        }
        else
        {
            ValidationMessage.ShowValidationMessage(MessageCenter.CashExpenseMaintenace.SaveServiceDetailOC, "SaveEmptyOC", this.Page);
        }
    }
    catch
    {
        ValidationMessage.ShowValidationMessage(MessageCenter.CashExpenseMaintenace.InsertOCError, "SaveEmptyOC", this.Page);
    }

    finally
    {
        //Rebinds the Grid
        populategrd_othercost();
        Dispose();
        GC.SuppressFinalize(this);
    }
}

这是我的业务层类

public class CashExpensesBL
{
    CEADataStoreDataContext CashExpensesDB = new CEADataStoreDataContext();

    public IEnumerable<CashExpense> get()
    {
        return CashExpensesDB.CashExpenses;
    }
    public IEnumerable<CashExpense> get(Expression<Func<CashExpense, Boolean>> express)
    {
        return CashExpensesDB.CashExpenses.Where(express);
    }
    public void insert(CashExpense item)
    {
        CashExpensesDB.CashExpenses.InsertOnSubmit(item);
    }
    public void delete(CashExpense item)
    {
        CashExpensesDB.CashExpenses.DeleteOnSubmit(item);
    }
    public void deleteDC(Guid servicedetailid)
    {
        CashExpensesDB.sp_deleteDefaultCost(servicedetailid);
    }
    public void submit()
    {
        CashExpensesDB.SubmitChanges();
    }
}
3个回答

4

将引用您的对象的变量赋值为null,然后使用GC.Collect();来强制进行垃圾回收。您可能需要连续调用两次以加速不可访问对象的处理过程。


tblCashExpenses = null; 然后在我的 try 块上加入 GC.Collect() 2 次? - anonymous1110
@anonymous1110 是的,请看看这是否有所帮助。 - Sergey Kalinichenko

4
你应该处理好DataContext。我没有看到它被移除,因此连接将保持打开状态,可能会保留引用(防止GC收回)。这可能是导致问题的原因。如果你不想手动处理,请在using块内执行事务。
根据业务层更新进行编辑 -
你可以像这样将方法包装在using块中:
public void insert(CashExpense item)
{    
   using(CEADataStoreDataContext CashExpensesDB = new CEADataStoreDataContext())
   {
       CashExpensesDB.CashExpenses.InsertOnSubmit(item); 
       CashExpensesDB.SubmitChanges();
   }
}

你好,我该如何处理数据上下文?我的业务层有一个单独的类,稍后我会添加它。 - anonymous1110
你可以直接调用 datacontext.Dispose 方法 - http://msdn.microsoft.com/zh-cn/library/system.data.linq.datacontext.dispose.aspx - keyboardP
嗨,我已经添加了我的业务层类。请看一下,谢谢。 - anonymous1110
你可以像上面那样更新其他方法。基本上,只有在需要时才打开DataContext,并在不需要时立即关闭它。Using块将在块的结尾自动调用Dispose。看看这是否有助于解决错误。 - keyboardP
SubmiteChanges() 代码移动到实际方法中,就像我在我的答案中所做的那样。这样,它将使用相同的 DataContext 运行(之前,在到达 submit 部分之前,DataContext 被删除了)。现在尝试保存它。是的,您可以注释掉第一行。 - keyboardP
显示剩余3条评论

1
将对象设置为null,然后调用:

GC.Collect(); GC.WaitForPendingFinalizers();


这不会起作用,因为单个GC.Collect()调用只是将对象移动到下一代。无法保证GC.Collect()甚至会做什么。 - Ferdinand Brunauer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接