D257aa96373ab45e0ef15cfdb60efe33

Show a BusyIndicator during long-tasks execution.

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static class BusyIndicator
{
private static readonly AsyncCallback   nullCallback    = delegate { };
        private static readonly object[]        emptyArray      = new object[] { };

        public static void ShowWhile(Control control, ThreadStart method)
        {
            if (method == null)
                throw new ArgumentException("Missing method definition", "method");

            if (control == null)
            {
                method.BeginInvoke(nullCallback, emptyArray);
                return;
            }

            control.Cursor = Cursors.WaitCursor;
            MethodInvoker callback = delegate   { control.Cursor = Cursors.Default; };
            AsyncCallback invoke   = delegate   { control.Invoke(callback); };
            method.BeginInvoke(invoke, emptyArray);           
        }
    }

sample usage

1
2
3
4
BusyIndicator.ShowWhile(this, delegate
{
    // Do stuff
});

Refactorings

No refactoring yet !

C63d2d886af30dbea99a341467ac116d

Darius Damalakas

September 27, 2007, September 27, 2007 00:34, permalink

2 ratings. Login to rate!

Seems ok to me. I doubt if refactoring could make it more readable.

Of course, unless you have many of such busy indicators, and of various kinds.

If it's the only busy indicators, then its very fine

D257aa96373ab45e0ef15cfdb60efe33

D_Guidi

September 27, 2007, September 27, 2007 00:41, permalink

No rating. Login to rate!

I've tested the code and this indicator is something like "Control-specific": this means that the BusyIndicator is showed only when the mouse is under the specific control, and not globally showed (better solutions exists for a global busy indicator using Cursor.Current).
This means that you could use (i think) more than one of this snippets at the same time, using different components as "host".
Now a better solution for a global wait cursor.

code provided by Marco De Sanctis

1
2
3
4
5
6
7
8
9
10
11
public class WaitCursor: IDisposable
{
public WaitCursor()
{
Cursor.Current = Cursors.WaitCursor;
}
public void Dispose()
{
Cursor.Current = Cursors.Default;
}
}

usage

1
2
3
4
using (new WaitCursor())
{
// some code here
}
C63d2d886af30dbea99a341467ac116d

Darius Damalakas

September 27, 2007, September 27, 2007 02:12, permalink

1 rating. Login to rate!

One problem with the original code is that after the method is invoked, it resets controls cursor to Cursors.Default, which might be not what was before.

Imagine, that the cursor was a magnify glass, and after the call it gets reset to Cursor.Default. IMHO, that's not what we want. We want the code to reset the cursor to previous state.

No code examples, since that's trivial to implement.

D257aa96373ab45e0ef15cfdb60efe33

D_Guidi

September 28, 2007, September 28, 2007 00:10, permalink

No rating. Login to rate!

I agree with you, Darius.
Simply, i need to store cursor's status in a field before the invoke, and use this field to restore the correct status in the callback.
Thanks for the suggest ;)

P.S: this service is so cool :)

Avatar

Avish

September 28, 2007, September 28, 2007 01:30, permalink

No rating. Login to rate!

Under .NET 2.0 and onwards, you can also use the UseWaitCursor property. This overrides other cursor settings without changing them, so once you set it to false again you automatically get your old cursor back.

1
2
3
4
5
6
7
8
9
10
11
12
public class WaitCursor: IDisposable
{
  public WaitCursor(Form form)
  {
    form.UseWaitCursor = true
  }
  
  public void Dispose()
  {
    form.UseWaitCursor = false
  }
}
D257aa96373ab45e0ef15cfdb60efe33

D_Guidi

September 28, 2007, September 28, 2007 03:41, permalink

No rating. Login to rate!

Cool :)
A suggest, You could (i think, looking at msdn: http://tinyurl.com/26rqaq) use a Control instead of a Form as a parameter... right?

1
2
3
4
5
6
7
8
9
10
11
12
public class WaitCursor: IDisposable
{
  public WaitCursor(Control control)
  {
    control.UseWaitCursor = true
  }
  
  public void Dispose()
  {
    control.UseWaitCursor = false
  }
}
1bcc70b9dd082ebd50053235210bdd9f

Nathan

October 1, 2007, October 01, 2007 10:37, permalink

No rating. Login to rate!

control.FindParent will find the form the control is on. Then you can set the cursor for the entire form.

Avatar

JH

October 23, 2007, October 23, 2007 13:38, permalink

No rating. Login to rate!

If I were using this in an MVP pattern I would try to leave the implementation of the wait state up to the view. This way I can re-use the code in an ajax control (set some visual wait indicator) or a winforms application (set the wait cursor).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface IView {
    void ShowWaitState();
    void ShowReadyState();
}

public class Presenter {
    private IView view;
    public Presenter(IView view) {
        this.view = view;
    }

    public void DoSomething() {
        view.ShowWaitState();
        // ... 
        view.ShowReadyState();
    }
}

Your refactoring





Format Copy from initial code

or Cancel