34

Yes, yes. I know they are 2 completely different technologies. I recently moved over to FAT development with C# and Windows Forms from web development. I always thought it was very easy to show a spinner using ajaxStart and ajaxStop, so the user knows something is occurring and to continue waiting.

Is there an equivalently simple technique for C# Windows Forms that can be implement globally? For example, if I am querying a DB and waiting for some results, normally the program becomes unresponsive for a few seconds and then starts working again after "processing". Is there some global way I can display a spinner while my program is "processing" instead of identifying all possible points in the program that could cause it to become unresponsive and just ripping off new threads?

Please let me know if I am being unclear.

bulltorious
  • 7,769
  • 4
  • 49
  • 78
  • for animated an image you can use this controller. http://www.codeproject.com/Tips/1004624/Gif-viewer-Snipper-control – xwpedram Jun 27 '15 at 21:21

9 Answers9

71

The standard Windows Forms way to do that is Cursor.Current = Cursors.WaitCursor;.

Does that work for you, or does it have to be an image?

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
  • 1
    I would like it to be an image...any recommendations? – bulltorious Jan 25 '12 at 19:05
  • Well, you can display an animation, but if your GUI thread is blocking, it won't update (the mouse cursor is handled by Windows, so it doesn't matter if your GUI blocks). So whatever you do, you will need to do your work in a separate thread. – Blorgbeard Jan 25 '12 at 19:11
  • Here's a good Q/A on [displaying an animated gif in c#](http://stackoverflow.com/questions/165735/how-do-you-show-animated-gifs-on-a-windows-form-c). – Blorgbeard Jan 25 '12 at 19:13
  • 3
    You can also use the [Control.UseWaitCursor](https://msdn.microsoft.com/en-us/library/system.windows.forms.control.usewaitcursor.aspx) property. – Jeff B Dec 23 '15 at 15:33
  • Excellent! So Oblivious! Thanks! – DeRamon Dec 01 '16 at 20:38
  • @DeRamon Did you mean "obvious"? – Robert Tausig Jan 02 '19 at 14:31
20

I am using Visual Studio Enterprise 2015. The suggested cursor styles/types given here, none of them worked with me.

The one that is working with me is:

private async void button_Click(object sender, RoutedEventArgs e)
{
    Cursor = Cursors.WaitCursor; // change cursor to hourglass type
    ThatProcessThatTookVeryLongTime();
    Cursor = Cursors.Arrow; // change cursor to normal type
}
AnasSafi
  • 5,353
  • 1
  • 35
  • 38
Amirizzuan
  • 353
  • 3
  • 9
  • 1
    Probably makes more sense to set the cursor back to default `Cursor.Current = Cursors.Default;` – dontbyteme Aug 30 '22 at 05:02
  • Using VS2022 with .NET6, I found the correct syntax to be Cursor = Cursors.WaitCursor. I didn't see any property called 'Wait' on the Cursor object. – Jason D Oct 17 '22 at 13:51
13

This is the way I like to use when I need a wait cursor; instead of writing a try-finally code.

    #region WaitCursor
    public static IDisposable BeginWaitCursorBlock()
    {
        return ((!_waitCursorIsActive) ? (IDisposable)new waitCursor() : null);
    }
    private static bool _waitCursorIsActive;
    private class waitCursor : IDisposable
    {
        private Cursor oldCur;
        public waitCursor()
        {
            _waitCursorIsActive = true;
            oldCur = Cursor.Current;
            Cursor.Current = Cursors.WaitCursor;
        }
        public void Dispose()
        {
            Cursor.Current = oldCur;
            _waitCursorIsActive = false;
        }
    }
    #endregion

Example use:

using (BeginWaitCursorBlock())
{
  ...
}
Koray
  • 1,768
  • 1
  • 27
  • 37
  • 2
    I've started using this with great success! – Hanny Mar 17 '17 at 14:23
  • @koray When I try to use your solution in one of my `WPF` projects, I get the errors: 1. At line oldCur = Cursor.Current;: `Cursor does not contain the definition for Current`. 2: At line Cursor.Current = Cursors.WaitCursor;: `Cursors does not contain the definition for WaitCursor`. Please advise. – nam Nov 29 '19 at 18:22
11

May I add this CodeProject link?

All you need is to build, drag from toolbar and use. The LoadingCircle component works without any trouble at all. Works like a charm, you can even customize it!

Joel
  • 7,401
  • 4
  • 52
  • 58
3

If your program becomes unresponsive, thats because you're doing real work on the UI thread. Move the work to a background thread, disable UI interaction as necessary to prevent the user from touching stuff while doing work, then when the background work finishes, ferry the results back to the UI thread using Control.Invoke, then update your UI with the results, then re-enable everything.

To implement the spinner, I use a PictureBox with a spinner gif in it. I disable it when the UI is idle, and enable it when I fire up the background worker.

The alternative is to change the mouse cursor to the 'waiting' cursor, which I'm not a huge fan of.

antiduh
  • 11,853
  • 4
  • 43
  • 66
2

Before processing : Cursor.Current = Cursors.WaitCursor;

ProcessesSomething();

After processing : Cursor.Current = Cursors.AppStarting;

1

Since .NET 4.5 (VS 2015+) you can use a combination of async and await with Progress for sending updates to UI thread:

click to open Related Artical

Community
  • 1
  • 1
BJ Patel
  • 6,148
  • 11
  • 47
  • 81
0

Another way would be a background worker or thread to do the job while running an animation, wait cursor or/and display loader GIF in the Forms/main thread.

VBWebProfi
  • 309
  • 3
  • 4
0

yes there is.

The easy was is to make two utility methods, one for enabling the "loading" indicator, and another for disabling that loading state.

Upon all initial ajax calls (or any other long calls), automatically call the enable method.

as soon as an oncomplete callback is fired, call the disable method from the oncomplete callback.

Kristian
  • 21,204
  • 19
  • 101
  • 176