2012-02-16

RestrictedFrequencyAction

Klasa jak sama nazwa wskazuje albo i nie służy do wywoływania delegatów z ograniczeniem: nie częściej niż pewien zadany czasy. Przydatna kiedy bardzo wiele wątków wprost bombarduje GUI żądaniami odświeżenia. W przypadku gdy pomiędzy kolejnymi akcjami nie upłynął określony czas aktualna akcja jest zapamiętywana jako kandydat do wywołania po upłynięciu czasu blokady. Należy pamiętać o tym, że z wszystkich akcji zablokowanych zostanie wywołana tylko ostania.

Nawet jeśli takie zjawisko w naszej aplikacji nie występuje, a może się zdarzyć, warto wykorzystać taką klasę by uniknąć problemów z czasem reakcji GUI.

Ja osobiście z tego modelu zrezygnowałem. Dlatego klasę utrwalam na blogu. Timer co 0.5s wystarcza w moim wypadku aż za nadto. Ponieważ wątki wykorzystują połączenia sieciowe real-time nie jest potrzebne.

public class RestrictedFrequencyAction
{
    private TimeSpan m_update_delta;
    private DateTime LastPerform;
    private volatile bool m_scheduled;
    private Object m_lock = new Object();
    private volatile Action m_action;

    public RestrictedFrequencyAction(int a_update_delta_ms)
    {
        m_update_delta = new TimeSpan(0, 0, 0, 0, a_update_delta_ms);
        LastPerform = DateTime.Now - m_update_delta - m_update_delta;
    }

    public void Perform(Action a_action)
    {
        lock (m_lock)
        {
            int t = (int)(m_update_delta - 
                (DateTime.Now - LastPerform)).TotalMilliseconds;

            if (t < 0)
            {
                LastPerform = DateTime.Now;
                a_action();
            }
            else
            {
                m_action = a_action;

                if (!m_scheduled)
                {
                    m_scheduled = true;

                    new Task(() =>
                    {
                        Thread.Sleep(t);
                        lock (m_lock)
                        {
                            LastPerform = DateTime.Now;
                            m_scheduled = false;
                            m_action();
                        }

                    }).Start();
                }
            }
        }
    }
}

Brak komentarzy:

Prześlij komentarz