Условный периодический таймер с использованием ручек ожидания - PullRequest
1 голос
/ 13 мая 2011

Мне нужен эквивалент таймера, который будет периодически выполнять некоторые конкретные действия (например, обновлять некоторый прогресс в базе данных или проверять наличие новых заданий для выполнения в базе данных).

Эти действия связаны с WaitHandle, который указываетесли работа должна быть выполнена или нет.Таким образом, в основном это может быть, например, AutoResetEvent, который устанавливается извне, когда в базе данных появляется новый объект и запускается поиск этих новых объектов.Таймер необходим, потому что я хочу ограничить количество запросов к базе данных.Поэтому, если поступит 10 новых уведомлений, AutomaticResetEvent будет установлен только один раз, и для всех них будет также только один запрос.

Мои первые попытки выглядят так:

class ConditionalScheduler
{
    public void AddConditionalAction(WaitHandle handle, Action action)
    {
        lock (syncRoot)
        {
            handles.Add(handle);
            actions.Add(handle, action);
        }
    }

    private readonly object syncRoot = new object();

    private readonly Dictionary<WaitHandle, Action> actions = new Dictionary<WaitHandle, Action>();
    private readonly List<WaitHandle> handles = new List<WaitHandle>();

    public void RunTimerLoop()
    {
        do
        {
            WaitHandle[] waitHandles = handles.ToArray();
            int index = WaitHandle.WaitAny(waitHandles);

            if (index >= 0)
            {
                WaitHandle handle = waitHandles[index];

                Action action;
                lock (syncRoot)
                {
                    action = actions[handle];
                }

                action();
            }
            Thread.Sleep(5000);
        } while (true);
    }

Проблема с этим подходом заключается в том, что WaitHandle.WaitAny выдаст мне только индекс первого запущенного WaitHandle.Поэтому, если у меня есть 2 или более сработавших WaitHandles, я буду выполнять только первые действия, а не другие.

У вас есть лучший дизайн для достижения требуемых результатов выполнения всех действий, которые были запущеныв течение указанного периода времени?Если бы это упростило вопрос, я мог бы использовать другой тип механизма уведомления вместо WaitHandles.

Спасибо!

Ответы [ 3 ]

1 голос
/ 13 мая 2011

Рассматривали ли вы использование встроенных классов таймера? System.Threading.Timer - это легковесная реализация, использующая ThreadPool или System.Timers.Timer, которая предоставляет связанные события и дополнительные функции.

1 голос
/ 13 мая 2011

Может быть, вы могли бы пойти с двумя потоками очереди / массового выполнения? Обратите внимание, что код вниз - это просто концепция, которую я пишу без визуальной студии, поэтому я делаю это по списку, лучше было бы это сделать с помощью очереди, но я не помню синтаксис без intellisense :) ...

private readonly Dictionary<WaitHandle, Action> actions = new Dictionary<WaitHandle, Action>();
    private readonly List<WaitHandle> handles = new List<WaitHandle>();
    private readonly List<WaitHandle> triggeredHandles = new List<WaitHandle>();

// thread 1
    public void CheckLoop()
    {
        do
        {
            WaitHandle[] waitHandles = handles.ToArray();
            int index = WaitHandle.WaitAny(waitHandles);

            if (index >= 0)
            {
                lock (triggeredHandles)
                {
                   triggeredHandles.Add(waitHandles[index]);
                }

            }            
        } while (true);
    }

// thread 2
public void RunLoop()
    {
        do
        {
            lock(triggeredHandles)
            {
                foreach (var th in triggeredHandles) {

                   Action action;
                   lock (syncRoot)
                   {
                       action = actions[th];
                   }

                   action();                   
                }
                triggeredHandles.Clear();
            }
            Thread.Sleep(5000);
        } while (true);
    }
0 голосов
/ 13 мая 2011

Вы, вероятно, сэкономите много хлопот, используя Reactive Extensions (Rx) - у него есть много отличных способов составить события так, как вы запрашиваете.

Этот сайт - это удобный способ узнать, на что способен rx.

...