1

I have a function that triggers a Task to start.

void function ()
{
  new Task(async () =>
  {
    // await network operation
  }).Start();
}

The function could get called many times very frequently. But I don't want the Task to be started each time, I want it to only start on the last trigger within let's say 5 seconds.

Here are the steps to what I want to do exactly

  1. function() gets called
  2. Have a delay for 5 seconds
  3. if function() was called within those 5 seconds, I wish to cancel any pending Tasks, and start a delay of 5 seconds all over again
  4. If function() was not called within those 5 seconds, I then wish to start the Task

Please guide me as how I would do that in C# .NET 4.5

Mohamed Heiba
  • 1,813
  • 4
  • 38
  • 67
  • Use a `Timer` or `DispatcherTimer` class to keep track of the 5 seconds. Use that to get started, and if you run into a problem while coding that, you might ask another question. – Tim S. May 18 '14 at 18:47
  • I did do a bit of research, and I already know about cancellation tokens for example. But I got stuck with the research and didn't know how to code sth as simple as that. Could you please help me ? Some code please ? – Mohamed Heiba May 18 '14 at 18:48
  • If the question, then, is more specifically, "how do I use a cancellation token?" (for example), you should edit it to reflect that. Your explanation of why ("Here are the steps to what I want to do exactly") is good, in case someone can suggest a better approach. But showing that you've considered a cancellation token and need help using it would be more to the point (and thus more useful and concise for all). And it shows it's not a "write my code for me" "question". – Tim S. May 18 '14 at 18:52
  • Thanks for your comment. No my problem wasn't how to use a cancellation token. My problem was whether I should use a cancellation token from the first place. My problem is how would I use timer/dispatcherTimer/cancellationToken to do what I want. – Mohamed Heiba May 18 '14 at 18:53
  • I'm using .NET on a client that doesn't support DispatcherTimer. Hence, I will be using Timer. Could you please tell me how to cancel the previous timer when the timer gets created ? i.e. how do I use the Timer class to do the steps I've written ? Your help is much appreacited – Mohamed Heiba May 18 '14 at 19:02
  • 2
    If you are open to using yet another library, [Reactive Extensions](http://msdn.microsoft.com/en-us/data/gg577609.aspx) could be used to implement this, using the [`Observable.Throttle`](http://msdn.microsoft.com/en-us/library/hh229298%28v=vs.103%29.aspx) extension method. – Mark May 18 '14 at 19:24

2 Answers2

2

The following code shows a simple Console Application that runs a task after 5 seconds and cancels the current task if a new one is started:

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Starting");
        Console.WriteLine("Press any key to call method or press Esc to cancel");

        do
        {
            Method();
        } while (Console.ReadKey(true).Key != ConsoleKey.Escape);
    }

    static Task delayTask = null;
    static CancellationTokenSource cancellationTokenSource = null;

    static void Method()
    {
        Console.WriteLine("Method called");

        if (delayTask != null)
        {
            cancellationTokenSource.Cancel();
        }

        cancellationTokenSource = new CancellationTokenSource();
        delayTask = Task.Delay(5000, cancellationTokenSource.Token);
        delayTask.ContinueWith((t) => {
            Console.WriteLine("Task running...");
        }, TaskContinuationOptions.NotOnCanceled);
    }
}

The code does not use async/await because those can't be used easily in a Console application (a Console Application doesn't have a SynchronizationContext). When using this code in a WinForms, WPF or ASP.NET application you can easily use async/await to improve upon the code. However, it does show the basic idea of using a CancellationTokenSource and combining a delay with another task.

Wouter de Kort
  • 39,090
  • 12
  • 84
  • 103
  • Wow thanks a lot, that's all what I'm looking for. I'll study your code thoroughly and apply it. Sincerely, much much Thanks! – Mohamed Heiba May 18 '14 at 19:23
0

A common term for this would be "debounce", and it's discussed here: C# event debounce

Alex from Jitbit
  • 53,710
  • 19
  • 160
  • 149