C# 在调用方法之前等待超时,并在连续调用时重置计时器



我的代码中有一个事件,可能会在某个时刻每秒触发多次。

但是,我想实现一种方法,使该方法在真正触发之前等待 500 毫秒,

如果在这 500 毫秒结束之前再次调用该方法,请重置计时器并再次等待 500 毫秒。

来自javascript,我知道这可以通过setTimeout或setInterval来实现。但是,我无法弄清楚如何在 C# 中实现这样的事情。

您可以使用包装在类中的System.Timers.Timer来获得所需的行为:

public class DelayedMethodCaller
{
    int _delay;
    Timer _timer = new Timer();
    public DelayedMethodCaller(int delay)
    {
        _delay = delay;
    }
    public void CallMethod(Action action)
    {
        if (!_timer.Enabled)
        {
            _timer = new Timer(_delay)
            {
                AutoReset = false
            };
            _timer.Elapsed += (object sender, ElapsedEventArgs e) =>
                {
                    action();
                };
            _timer.Start();
        }
        else
        {
            _timer.Stop();
            _timer.Start();
        }
    }
}

然后可以按以下方式使用它:

public class Program
{
    static void HelloWorld(int i)
    {
        Console.WriteLine("Hello World! " + i);
    }
    public static void Main(string[] args)
    {
        DelayedMethodCaller methodCaller = new DelayedMethodCaller(500);
        methodCaller.CallMethod(() => HelloWorld(123));
        methodCaller.CallMethod(() => HelloWorld(123));
        while (true)
            ;
    }
}

如果您运行该示例,您会注意到"你好世界!123" 仅显示一次 - 第二次调用只是重置计时器。

如果需要在

再次调用该方法时重置计时器,请考虑查看 ManualResetEvent 类:

https://msdn.microsoft.com/en-us/library/system.threading.manualresetevent(v=vs.110).aspx

您可以使用它来通知一个或多个等待线程发生了事件。

您可以使用带锁定功能的 Thread.Sleep()

private object locking = new object();
lock (locking )
{
    Thread.Sleep(500);
    //Your code to run here
}

https://msdn.microsoft.com/en-us/library/system.threading.thread.sleep(v=vs.110).aspx

刚刚用System.Threading.Thread编写了超级简单的类;用一点不同的方法用法。

var delayedCaller = new DelayedTimeout(() => HelloWorld(123), 500, false);
delayedCaller.ResetTimer();
delayedCaller.ResetTimer();

目前,您可以使用以下类非常简单地做到这一点

public class DelayedTimeout
{
    readonly Timer _timer;
    readonly int _timeoutMs;
    public DelayedTimeout(TimerCallback callback, int timeoutMs, bool startNow)
    {
        _timeoutMs = timeoutMs;
        // Should we start now
        var currentTimeoutMs = startNow ? _timeoutMs : Timeout.Infinite;
        _timer = new Timer(callback, null, currentTimeoutMs, Timeout.Infinite);
    }
    // Constructor overloading
    public DelayedTimeout(Action callback, int timeoutMs, bool startNow) :
        this(delegate (object? obj) { callback.Invoke(); }, timeoutMs, startNow)
    {}
    public void ResetTimer()
    {
        _timer.Change(Timeout.Infinite, Timeout.Infinite); // Stop the timer
        _timer.Change(_timeoutMs, Timeout.Infinite); // Stop the timer
    }
}

相关内容

  • 没有找到相关文章

最新更新