如何在x秒内仅使用最后一个触发器启动任务?

时间:2014-05-18 18:43:40

标签: c# .net c#-4.0 scheduled-tasks task

我有一个触发任务启动的功能。

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

该函数可以非常频繁地被调用多次。但我不希望每次都启动任务,我希望它只能在最后一次触发时启动,比如5秒钟。

以下是我想要做的事情的步骤

  1. function()被调用
  2. 延迟5秒
  3. 如果在5秒内调用了function(),我希望取消任何待处理的任务,并重新开始5秒的延迟
  4. 如果在5秒内没有调用function(),那么我希望启动任务
  5. 请指导我在C#.NET 4.5中如何做到这一点

2 个答案:

答案 0 :(得分:2)

以下代码显示了一个简单的控制台应用程序,该应用程序在5秒后运行任务,如果启动了新任务,则取消当前任务:

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);
    }
}

代码不使用async / await,因为它们不能在控制台应用程序中轻松使用(控制台应用程序没有SynchronizationContext)。在WinForms,WPF或ASP.NET应用程序中使用此代码时,您可以轻松使用async / await来改进代码。但是,它确实显示了使用CancellationTokenSource并将延迟与其他任务相结合的基本思路。

答案 1 :(得分:0)

通常将其称为“去抖动”,并在此处进行讨论:C# event debounce