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 1,854 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's avatar

    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's avatar

      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

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