The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 4,262 other subscribers

.NET/C#: Using IDisposable to restore temporary settrings example: TemporaryCursor class

Posted by jpluimers on 2012/01/26

This is WinForms code from a long time ago, but the concept of using an IDisposable interface to do resource cleanup and restore a temporary setting is very valid.

You use the code below like this:

        private void myMethod()
        {
            // set busy cursor
            using (IDisposable waitCursor = new TemporaryCursor(this, System.Windows.Forms.Cursors.WaitCursor))
            {
                // logic that takes a long while
            }
        }

The code below implements the TemporaryCursor class; you can assign any System.Windows.Forms.Cursors item you want.

It restores the cursor upon these three “events”:

Most often the IDispose pattern is being used to make sure that resources get cleaned up. If you think of a wait cursor as a temporary resource, this example becomes much easier to remember.

Of course this is not limited to the System.Windows.Forms realm, you can just as well use this for non-visual temporaries, and other kinds of UIs like ASP.NET, WPF or SilverLight.

using System.Windows.Forms;

namespace bo.Windows.Forms
{
    public class TemporaryCursor : IDisposable
    {
        private Control targetControl;
        private Cursor savedCursor;
        private Cursor temporaryCursor;
        private bool disposed = false;

        public TemporaryCursor(Control targetControl, Cursor temporaryCursor)
        {
            if (null == targetControl)
                throw new ArgumentNullException("targetControl");
            if (null == temporaryCursor)
                throw new ArgumentNullException("temporaryCursor");
            this.targetControl = targetControl;
            this.temporaryCursor = temporaryCursor;
            savedCursor = targetControl.Cursor;
            targetControl.Cursor = temporaryCursor;
            targetControl.HandleDestroyed += new EventHandler(targetControl_HandleDestroyed);
        }

        void targetControl_HandleDestroyed(object sender, EventArgs e)
        {
            if (null != targetControl)
                if (!targetControl.RecreatingHandle)
                    targetControl = null;
        }

        // public so you can call it on the class instance as well as through IDisposable
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (null != targetControl)
                {
                    targetControl.HandleDestroyed -= new EventHandler(targetControl_HandleDestroyed);
                    if (temporaryCursor == targetControl.Cursor)
                        targetControl.Cursor = savedCursor;
                    targetControl = null;
                }
                disposed = true;
            }
        }

        // Finalizer
        ~TemporaryCursor()
        {
            Dispose(false);
        }
    }
}

–jeroen

4 Responses to “.NET/C#: Using IDisposable to restore temporary settrings example: TemporaryCursor class”

  1. […] A long while ago, I wrote about a (then overdue post) on .NET/C#: Using IDisposable to restore temporary settrings example: TemporaryCursor class. […]

  2. […] null; } disposed = true; } } // Finalizer ~TemporaryCursor() { Dispose(false); } } } References: .NET/C#: Using IDisposable to restore temporary settrings example: TemporaryCursor class from our NCG partner Jeroen Pluimers at the The Wiert Corner blog. […]

  3. Ramon said

    Moet in de Dispose method de parameter disposing niet gecheckt worden en moet de check if (temporaryCursor == targetControl.Cursor)
    niet (temporaryCursor != targetControl.Cursor) zijn?

    • jpluimers said

      Lets keep this in English :)
      “Should inside the Dispose method:

      1. the parameter disposing be checked
      2. the check if (temporaryCursor == targetControl.Cursor) be (temporaryCursor != targetControl.Cursor)

      ?”
      Answer:

      1. yes, and no. That normally is the correct IDisposabla pattern implementation for unmanaged resources (http://msdn.microsoft.com/en-us/library/b1yfkh5e.aspx). I will correct this shortly to implement the disposed. No, even though this is a managed resource, you need to always restore it, be it through a using/IDisposable usage, or through the finalizer (when someone calls it without using/IDisposable).
      2. no, as in the example both temporaryCursor is Cursors.WaitCursor and targetControlCursor should only be restored if it indeed still has that value.

      –jeroen

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.