erexo
erexo

Reputation: 533

How to dispatch every previous Task that was created by particular event

I have an event in my WPF .NET 4.5 application that can be triggered up to 10 times per second, the event is computing data that is not required that often so I'm looking for a way to remove unnecessary computation stress and call the method if event wasn't triggered for 3 seconds. I thought about using async functionality like that:

private async Task DoWork()
{
    await Task.Delay(3000);
    ...
}

private void Event()
{
    Task.Run(() => DoWork());
}

I'm not really sure about how to elegantly handle disposing of unwanted Tasks, ie. when user trigger the event, every task that was created by that event should be terminated and it should be as fast as possible. I've tried with CancellationToken but I'm not sure this is the right approach for my case

Upvotes: 0

Views: 91

Answers (2)

erexo
erexo

Reputation: 533

That was my solution based on @Fabjan answer.

    private static void RunSingleTask(ref CancellationTokenSource cts, int delay, Action func)
    {
        if (cts != null)
        {
            cts.Cancel();
            cts.Dispose();
        }

        cts = new CancellationTokenSource();
        var token = cts.Token;
        Task.Run(async () =>
        {
            try
            {
                await Task.Delay(delay, token);
            }
            catch (TaskCanceledException)
            {
                return;
            }

            await Application.Current.Dispatcher.BeginInvoke(func); 
        });
    }

Upvotes: 1

Fabjan
Fabjan

Reputation: 13676

You can use CancellationTokenSource to let the code inside task know that it is canceled:

private CancellationTokenSource CancellationTokenSource { get; } = new CancellationTokenSource ();

Let's change:

private async Task DoWork()
{
    await Task.Delay(3000);
    ...
}

To:

private async Task DoWork(int timeout = 3000)
{
    await Task.Delay(timeout, CancellationTokenSource.Token);
    if(!CancellationTokenSource.Token.IsCancellationRequested)
    {
       ...
    }
}

Now we can cancel our task if required:

CancellationTokenSource.Cancel();

Task.Delay will observe the CancellationToken and if it is in a Canceled state it will abort the task execution. Later in code we check whether we need to do anything or not.

Upvotes: 2

Related Questions