Question

I have following code that uses “using” block on TableHeaderCell, LiteralControl , HyperLink and GridViewRow (try..finally). The code is working as indented. Is there any issue/pitfall in disposing the controls with “using” block as shown below? If yes, can you provide any msdn reference that shows details of the pitfall?

    protected void grdTransactions_RowCreated(object sender, GridViewRowEventArgs e)
    {

        if (e != null)
        {
            if (e.Row.RowType == DataControlRowType.Header)
            {
                GridViewRow newHeaderRow = null;
                try
                {

                    newHeaderRow = new GridViewRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal);

                    using (TableHeaderCell cellFirst = new TableHeaderCell())
                    {
                        cellFirst.ColumnSpan = 1;
                        cellFirst.Text = "FIRST";
                        newHeaderRow.Cells.Add(cellFirst);
                    }


                    using (TableHeaderCell cellAssociate = new TableHeaderCell())
                    {
                        GetTableCell(cellAssociate,"tableColGroupAssociate", 4, "associateHide", "Associate Transaction Info");
                        newHeaderRow.Cells.Add(cellAssociate);
                    }

                    newHeaderRow.Cells.Add(cellAssociate);
                    ((GridView)sender).Controls[0].Controls.AddAt(0, newHeaderRow);

                }
                finally
                {
                    if (newHeaderRow != null)
                    {
                        newHeaderRow.Dispose();
                        newHeaderRow = null;
                    }
                }

            }
        }




    }

Helper Method

    private static void GetTableCell(TableHeaderCell cellAssociate, string cssClassName, int colSpan, string hideClassName, string displayName)
    {
        cellAssociate.ColumnSpan = colSpan;
        cellAssociate.CssClass = cssClassName;

        using (LiteralControl ltlText = new LiteralControl())
        {
            ltlText.Text = displayName;
            cellAssociate.Controls.Add(ltlText);
        }

        using (HyperLink lnkHide = new HyperLink())
        {
            lnkHide.Text = SupportToolUIResource.HideLinkText;
            lnkHide.CssClass = hideClassName;
            lnkHide.Target = SupportToolUIResource.HideLinkTarget;
            cellAssociate.Controls.Add(lnkHide);
        }


    }

Reference:

  1. Why would I need to call dispose on ASP.NET Controls?
Was it helpful?

Solution 2

Thanks to @Tim Medora for the explanation and the link Why would I need to call dispose on ASP.NET Controls? .

Some points of interest are:

  1. What we need to do is make sure that new controls are added is in the Controls’ collection so that it will be disposed when the Page is disposed.
  2. Control objects implement the IDisposable interface. Each parent control can call Dispose on all of its children
  3. Any properly-written object that implements IDisposable and has state data that is actually cleaned up during the dispose process should throw an ObjectDisposedException if any of its public/protected/internal properties or methods are accessed after it has been disposed. (Assume invalid state after Dispose has been called.) Some types will ignore this rule if they don't actually have anything to clean up, and don't have to worry about invalid state.

Conclusion

No need to use "using" block on webcontrols. Also, it may cause issues if "using" block is used on webcontrols.

OTHER TIPS

Even if you are "done" with the control, the page will access the control when it renders, so disposing them during construction doesn't make much sense. In one of your examples you are using one of the controls you just disposed, which also doesn't make sense.

Call Dispose when you are finished using the Control. The Dispose method leaves the Control in an unusable state. After calling this method, you must release all references to the control so the memory it was occupying can be reclaimed by garbage collection.

The description of the Disposed event raised by the control also hints at the intended usage:

Occurs when a server control is released from memory, which is the last stage of the server control lifecycle when an ASP.NET page is requested.

Source: http://msdn.microsoft.com/en-us/library/system.web.ui.control.dispose.aspx
Source: http://msdn.microsoft.com/en-us/library/system.web.ui.control.disposed.aspx
See Also: https://stackoverflow.com/a/3151072/453277

So in theory:

  1. Build control tree.
  2. Page begins rendering.
  3. Page looks at controls added to tree.
  4. Controls have been disposed.
  5. Potential problems.

Here is the implementation of IDisposable (from Control). Note how it alters the container and event-related values.

public virtual void Dispose()
{
    if (this.Site != null)
    {
        IContainer container = (IContainer)this.Site.GetService(typeof(IContainer));
        if (container != null)
        {
            container.Remove(this);
            EventHandler eventHandler = this.Events[Control.EventDisposed] as EventHandler;
            if (eventHandler != null)
            {
                eventHandler(this, EventArgs.Empty);
            }
        }
    }
    if (this._occasionalFields != null)
    {
        this._occasionalFields.Dispose();
    }
    if (this._events != null)
    {
        this._events.Dispose();
        this._events = null;
    }
}

When to Dispose

That isn't to say you shouldn't dispose your resources; if a control needs to dispose resources, it is certainly free to do so. Perhaps a control accesses a database; I would wrap the database code inside a using block inside the control.

In practicality, this style creates a large block of code for something which could be expressed more simply.

using (LiteralControl ltlText = new LiteralControl())
{
    ltlText.Text = displayName;
    cellAssociate.Controls.Add(ltlText);
}

// could become
cellAssociate.Controls.Add( new LiteralControl { Text = displayName } );
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top