4

Say, I created a custom button which includes some animation which is played when the button is clicked. The animation takes 500ms. During that time (until the animation is over), the button should not receive any inputs, and so should other items wait for it to end.

If I implement it like this:

public async void Clicked()
{
    await Animate();
}

the UI thread won't be blocked and user will be able to press the button again during that time, or press Back button, or do something else that I don't want him to be able to do.

If I implement it like this:

public void Clicked()
{
    Animate();
}

the UI thread will be blocked until the Animate returns.

My question is, is it a good idea to block UI thread in order to prevent user from double-clicking an item?

If no, what approach is considered good?

nicks
  • 533
  • 2
  • 6
  • 14
  • 2
    If you block, the user will not be able to stop the animation and exit the program. – JacquesB Sep 10 '16 at 09:22
  • If you block UI thread, all UI operations, which user performs, will start getting processed right after your method finishing. So if user clicked the button during the blocked period, it will get then pressed and method will start executing again. Moreover, if your window won't pick any message from the message queue in certain amount of time (a couple of seconds), you'll get the "milky" effect and message about your application not responding. So, generally, blocking UI thread is **never a good idea**. – Spook Aug 03 '21 at 12:02

2 Answers2

7

The better approach is to keep track if the animation currently runs or not, like this:

bool animationRuns=false;

async void Clicked()
{
    if(animationRuns)
       return;
    animationRuns=true;
    await Animate();
    animationRuns=false; 
}

That way, your UI will still be responsive while the animation is running, but the user cannot start it accidentally twice again. If there are other events which shall be disabled during the anim runs, you can test the animationRuns flag there as well.

Doc Brown
  • 199,015
  • 33
  • 367
  • 565
2

First, setup an application OnIdle handler. For a WinForms application this is pretty straightforward, for WPF there are a number of alternatives listed here https://stackoverflow.com/questions/3872992/how-do-we-do-idle-time-processing-in-wpf-application

In this handler, set the enabled state of all the controls you want to disable while your application is busy. Use your busy state condition for the enabled values.

Martin Maat
  • 18,218
  • 3
  • 30
  • 57
  • [More discussion of Application Idle](https://stackoverflow.com/a/5415399/199364). Though I'm a bit concerned that an accidental second click might be possible before Idle handler runs to disable the button. – ToolmakerSteve Nov 20 '19 at 16:47