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”:
- The Dispose method either called directly on the class, or through the IDisposable.Dispose via for instance a using statement
- The ~TemporaryCursor desctructor syntax implementing the finalizer
- The HandleDestroyed event on the Control
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