2

I have a panel called displayPanel. In this panel I show a UserControl depending on which button from a row of buttons is clicked using a method along the lines of:

private void button_Click(Object sender, EventArgs e)
{
    displayPanel.Controls.Clear();
    displayPanel.Controls.Add(UserControl);
}

In one of the user controls i had a method along the lines of:

private void StartWork()
{
    Cursor.Current = Cursors.WaitCursor;
    DoWork();
    Cursor.Current = Curors.Default;
}

I then changed this to:

private async void StartWork(Object sender, EventArgs e)
{
    Application.UseWaitCursor = true;
    await DoWork();
    Application.UseWaitCursor = false;
}

This allows me to change which UserControl is displayed in the displayPanel while DoWork() is busy in the background. Starting DoWork() and not changing usercontrols shows a wait cursor untill DoWork() finishes, then its the default cursor again.

Starting DoWork() and then changing the displayed usercontrol also shows the wait cursor untill DoWork() is done, and then right back to the default cursor. However! If I now change back to the usercontrol that initiated DoWork() then said usercontrol displays a wait cursor.

Printing all the UserWaitCursor and Cursor properties for the DoWork() initiating usercontrol showns false and Cursor.WaitCursor respectively. (Instead of the expected: false and Cursor.Default)

Now I found that I can "Fix" my problem by calling UserControl.UseWaitCursor = !UserControl.UseWaitCursor twice. But this feels wrong and I would rather fix it properly. Which brings me to my question: Why is my UserControl.Cursor stuck at Cursor.WaitCursor after setting Application.UseWaitCursor to false in DoWork()?

Edit: I made a simple project where I was able to reproduce the problem. In the following pastebin are a form and 2 usercontrols that are able to reproduce the discibed problem: http://pastebin.com/PUkvJxMw

Skyqula
  • 429
  • 1
  • 8
  • 17
  • 1
    It is not a very smart property, it only signals the *intention* to show an hourglass. But if the user doesn't move the mouse then it won't happen. And it won't happen when you hang the UI thread since it then will no longer get the "the mouse moved" messages, it is busy executing DoWork. http://stackoverflow.com/a/302865/17034 – Hans Passant Feb 14 '17 at 14:27
  • Except the UI thread doesnt hang. Its not busy with `DoWork()` as the async await part puts it in a background threat. Likewise, your linked solution doesnt work either, it gives the exact same result (cursor updates correctly, just the original control is stuck with the wait cursor incase of switching the displayed control during the execution of `DoWork()`). – Skyqula Feb 15 '17 at 09:18
  • Erm, if you use async then you shouldn't have a need for a wait cursor. Since the UI is still responsive. Maybe it is not, fire-hosing the UI thread with async code that uses Begin/Invoke() too often is a common mistake. That also prevents a control from painting itself so makes the appearance of "stuck". A bit imprecise to guess what really is going on. Btw, using Controls.Clear() is a nasty bug, it does not call Dispose() on the removed controls. That can get out of hand badly. – Hans Passant Feb 15 '17 at 09:52
  • Well, the program itself is still responsive, everything still works. Even after `DoWork()` is done. Its just the control's cursor property that doesnt get updated. – Skyqula Feb 15 '17 at 09:56
  • As for the`Controls.Clear()`, its fully intentional that the controls arent disposed. The creation of the control's we use is expensive and we just use it to swap the displayed control. – Skyqula Feb 15 '17 at 09:59
  • It is too vague to stick a fork into. Use async. Do *not* change the cursor, the UI is still responsive so the user doesn't need a cue that it isn't. Just make sure that the user cannot start the async task again until it is done. Trivially done by setting a button's Enabled property to false before and back to true after. Serves as feedback as well. – Hans Passant Feb 15 '17 at 10:01
  • I think you are right, I should find another way to communicate that the desired task is running. Thanks for the suggestion! – Skyqula Feb 15 '17 at 10:09

0 Answers0