0

I have 1 method and 1 event

private void Grid_MouseWheel(object sender, MouseWheelEventArgs e)
    {
        if (currentSection == OsuSection.PreLoad)
            return;
        if(VolumeMixer.Visibility == Visibility.Collapsed)
        {
            isAwaitVolumeGaugeRunning = true;
            VolumeMixer.Visibility = Visibility.Visible;
            DoubleAnimation fadeIn = new DoubleAnimation(0, 1, TimeSpan.FromSeconds(0.1), FillBehavior.Stop);
            fadeIn.Completed += (object senderr, EventArgs ee) => { VolumeMixer.Opacity = 1; };
            VolumeMixer.BeginAnimation(OpacityProperty, fadeIn);
            Fadeout();
            return;
        }
        if (e.Delta > 0)            
            workingResources.MasterVolumeValue += 5;
        else
            workingResources.MasterVolumeValue -= 5;
    }

    private async Task Fadeout()
    {
        await Task.Delay(1500);
        if (!isAwaitVolumeGaugeRunning)
            return;
        DoubleAnimation fadeOut = new DoubleAnimation(1, 0, TimeSpan.FromSeconds(0.1), FillBehavior.Stop);
        fadeOut.Completed += (object sender, EventArgs e) => 
        {
            VolumeMixer.Opacity = 0;
            VolumeMixer.Visibility = Visibility.Collapsed;
        };
        VolumeMixer.BeginAnimation(OpacityProperty, fadeOut);
        isAwaitVolumeGaugeRunning = false;
    }

When the user scroll, the Canvas VolumeMixer FadeIn and the MasterVolueValue is Bind to a TextBlock and a Media Element. But if while user are continuously scrolling after 1.5 sec the Canvas FadeOut and FadeIn (took 0.2 sec). So I want The canvas Hide after user complete scrolling 1.5 second

  • 1
    You can pass `CancellationToken` and after 1 sec wait check if it needs to be aborted. – FCin May 07 '18 at 07:32
  • You aren't asking how to abort a task. You are asking how to prevent *button clicks* before another task finishes – Panagiotis Kanavos May 07 '18 at 07:37
  • No, I want to abort the MessageBox.Show() – Null Reference Exception May 07 '18 at 07:37
  • The MessageBox.Show() need to appear right after second . If you click too fast, the MessageBox will show less than 1 second compare to the last user Click – Null Reference Exception May 07 '18 at 07:38
  • @QuanVN in this case the question has nothing to do with tasks, async/await or aborting. You should probably explain what you really want, not how you think it can be implemented. By the time `MessageBox.Show` is called the task is already **finished** and execution is back in the UI thread. – Panagiotis Kanavos May 07 '18 at 07:39
  • 3
    @QuanVN BTW `async void` is only meant for event handlers. Methods that don't return a result should use the `async Task SomeMethod()` signature. Your TaskMethod's signature should be `async Task TaskMethod()` and the event handler `async void Btn_Click`. The handler should look like `private async void Btn_Click(..){...; await TaskMethod();}`. If you disable the button at the start of the handler and enable it at the end, users won't be able to click it before the task finishes – Panagiotis Kanavos May 07 '18 at 07:45
  • The new edit is the problem I've got, the previous is simplified so I think it don't have enough detail – Null Reference Exception May 07 '18 at 07:54

2 Answers2

1

As FCin mentioned, you can use CancellationToken. However, in this scenario, I'm wondering if it would be better to gray out the message box as soon as the button is pressed? Then reenable the button once the async operation is completed. To me, that seems cleaner then dealing with CancellationTokens and restarting the async process all over again.

Andrew
  • 1,581
  • 3
  • 18
  • 31
1

Create a CancellationTokenSource and pass the value of it's Token property to the method you want to cancel. To abort call the Cancel() method of your CancellationTokenSource object.

private static CancellationTokenSource _cancellationTokenSource;

private void Btn_Click(object sender, EventArgs e)
{
    if(previousPress)
    {
        _cancellationTokenSource.Cancel();
    }
    _cancellationTokenSource = new CancellationTokenSource();
    TaskMethodAsync(_cancellationTokenSource.Token);
}
private async Task TaskMethodAsync(CancellationToken cancellationToken)
{
    await Task.Delay(1000, cancellationToken);
    MessageBox.Show("Hello World!");
}
renklus
  • 776
  • 6
  • 17
  • 1
    async void methods are bad practice. You can use async Task in this case. Also by convention, async method names should end with Async word. – dlxeon May 07 '18 at 08:01
  • To get rid of static variable, the `TaskMethod` could be made [local](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/local-functions). – JohnyL May 07 '18 at 08:01
  • I can't make the event async because I declare the event in xaml – Null Reference Exception May 07 '18 at 08:05