仅当经过 3 秒时,才能再次调用方法

本文关键字:调用 方法 经过 秒时 | 更新日期: 2023-09-27 18:31:51

我想实现某种方法来防止方法立即被多次调用。 例如,想象一下,如果我有一个这样的类:

class Example
{
    public void MyFunction()
    {
        // do something
    }
}

用户可以调用MyFunction但前提是自上次调用以来已经过去了 3 秒。如果在 3 秒之前调用它,则不应发生任何操作(应忽略调用)。

我该怎么做?

编辑:

我不想使用Thread.Sleep.我在想也许使用 System.Timer 的计时器类。但不知道我将如何使用它来满足我的需要。

仅当经过 3 秒时,才能再次调用方法

我认为这里不需要使用计时器。您可以使用Stopwatch

class Example
{
    private static readonly TimeSpan MinInterval = TimeSpan.FromSeconds(3);
    private readonly Stopwatch stopwatch = new Stopwatch(); // Stopped initially
    public void MyFunction()
    {
        if (stopwatch.IsRunning && stopwatch.Elapsed < MinInterval)
        {
            return;
        }
        try
        {
            // Do stuff here.
        }
        finally
        {
            stopwatch.Restart();
        }
    }
}

请注意,这不是线程安全的...多个线程可以在同一实例上同时执行该方法。但是,每个实例都使用单独的秒表,因此多个线程可能会使用多个实例 - 如果要禁止所有实例的调用,则需要为秒表使用静态字段,并且一定要添加锁定以便安全地访问它。

另请注意,尽管您可以使用DateTime来检测上次执行时间,但用户更改系统时钟很容易出错。

此处使用 try/finally 是为了避免快速连续的多个调用由于抛出异常而失败。同样,这可能不是您想要的...您应该考虑是否希望在呼叫失败时重置秒表。

Diagnostics.Stopwatch来做:

class Program
{
    static Stopwatch stopwatch = new Stopwatch();
    static void Main(string[] args)
    {
        stopwatch.Start();
        Todo();
        Thread.Sleep(4000);
        Todo();
    }
    public static void Todo()
    {
        if(stopwatch.Elapsed.TotalSeconds > 3)
        {
            // do stuff
            stopwatch.Restart();
        }
    }
}

您可以声明类的私有DateTime字段,将方法的上次调用时间存储在那里,并检查与当前时间的差异:

class Example
{
    private DateTime _MyFunctionLastCallTime = DateTime.MinValue;
    private object _Lock = new object();
    public void MyFunction()
    {
        lock(_Lock)
        {
            var now = DateTime.UtcNow;
            if ((now - _MyFunctionLastCallTime).TotalSeconds < 3)
                return;
            _MyFunctionLastCallTime = now;
            // the rest of code
        }
    }
}

你不需要"阻止"任何东西,也不需要做任何与线程相关的事情,只需存储上次执行的时间并退出(或抛出异常或做任何你想做的事情),如果它被调用得太快

private DateTime LastCalled;
public void MyFunc()
{         
    if (LastCalled > DateTime.Now.AddSeconds(-3)
    {
         return; // or do whatever else you want, throw an exception etc
    };
    LastCalled = DateTime.Now;
    // Your actual method code here
}