Alan2
Alan2

Reputation: 24572

How can I stop a method being called more than once in 5 seconds?

I have this method:

    public static async Task OpenPageAsync(string route)
    {
        await Shell.Current.GoToAsync(route, true);
    }

If the method is called more than once in 5 seconds I would like the second call to be ignored. Has anyone come across a way to deal with this need?

Note that if it helps I do have access to create properities at the App level like this etc.

public partial class App : Application
{
    public static int LastTapTime;
    public static int TapTime;

Upvotes: 1

Views: 373

Answers (1)

Fortega
Fortega

Reputation: 19682

In our project, we have created a 'MaxFrequencyUpdater' for exactly that cause. Only difference: if within 5 seconds a new call comes in, it is delayed and executed after the 5 seconds interval.

namespace Utils
{
    public class MaxFrequencyUpdater
    {
        private readonly WinformsExceptionHandler _exceptionHandler;

        private readonly string _name;
        private readonly int _millis;
        private MethodInvoker _currentMethod;
        private DateTime _lastExecuted = DateTime.MinValue;
        private readonly object _updaterLockObject = new object();

        public MaxFrequencyUpdater(string name, int maxFrequencyInMillis, WinformsExceptionHandler exceptionHandler)
        {
            _name = name;
            _exceptionHandler = exceptionHandler;
            _millis = maxFrequencyInMillis;
        }
        
        public void Update(MethodInvoker method)
        {
            lock (_updaterLockObject)
            {
                _currentMethod = method;
            }
            Task.Run(HandleWork);
        }

        private void HandleWork()
        {
            lock (_updaterLockObject)
            {
                // No longer bother, someone else handled it already
                if (_currentMethod == null) return;

                var now = DateTime.Now;
                var delay = (int)(_millis - now.Subtract(_lastExecuted).TotalMilliseconds);

                // Post-pone if too soon
                if (delay > 0)
                {
                    Task.Delay(delay).ContinueWith(HandleWork);
                }
                else
                {
                    try
                    {
                        _currentMethod.Invoke();
                    }
                    catch (Exception e)
                    {
                        _exceptionHandler.HandleException(e);
                    }

                    _lastExecuted = now;
                    _currentMethod = null;
                }
            }
        }
    }
}

usage:

_maxFrequencyUpdater.Update(() =>
        {
            doSomething();
        });

Upvotes: 1

Related Questions