1

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;
Alan2
  • 23,493
  • 79
  • 256
  • 450
  • 2
    The question is closed as a duplicate, but the linked question is hardly an answer, from what I can see. https://stackoverflow.com/questions/28472205/c-sharp-event-debounce might help instead. – mlibby Jun 30 '20 at 11:33

1 Answers1

1

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();
        });
Fortega
  • 19,463
  • 14
  • 75
  • 113