Как создать планировщик (например, чтобы запланировать твиты или запрос API)

У меня есть таблица пунктов расписания, они могут быть запланированы на одно и то же время. Мне интересно, как заставить их все выполняться в нужное время, когда:

Проблема, которую я вижу, заключается в том, что для выполнения одного запланированного элемента (например, запланированного сообщения в твиттере) требуется запрос API, который может занять до секунды или двух - возможно, дольше. Если я выполняю их последовательно + одновременно слишком много запланированных элементов, время их выполнения может быть позже запланированного времени.

Как мне построить эту систему «расписания», которая позволит избежать этих проблем? Есть советы, советы?

Спасибо!


person rksprst    schedule 26.01.2010    source источник


Ответы (4)


Я бы использовал службу Windows для этого. Затем каждый из элементов должен быть запланирован асинхронно с помощью процесса BackgroundWorker. Это позволит быстро запускать все запланированные процессы асинхронно, чтобы они не конфликтовали и не зависели от завершения предыдущего перед запуском.

person Joel Etherton    schedule 26.01.2010
comment
Я согласен, лучше позволить фреймворку обрабатывать потоки. - person Jason Rowe; 26.01.2010
comment
Итак, вы бы сказали, что это хороший процесс: 1. Перейти к базе данных, получить запланированные элементы на эту минуту 2. Перебрать запланированные элементы, запуская каждый из них как фоновый процесс 3. Приостановить до следующей минуты 4. Повторить? И работает ли это как служба Windows? - person rksprst; 26.01.2010
comment
Я бы. Я бы также рекомендовал создать класс менеджера состояния, чтобы отслеживать все это. Каждый BackgroundWorker сможет независимо отчитываться о своем прогрессе. Таким образом, вы сможете отслеживать, были ли какие-либо независимые сбои, сообщения и т. д. - person Joel Etherton; 26.01.2010

Возможно, вы захотите рассмотреть Quartz.NET. Дает вам большую гибкость с точки зрения планирования и выполнения задач.

person o.k.w    schedule 26.01.2010

Если вы не предпримете шагов, чтобы воспользоваться преимуществами асинхронных API, существующих для всех операций ввода-вывода, единственным подходом будет использование множества потоков. Рассмотрим .net ThreadPool, так как это может увеличить количество потоков, когда слишком много рабочих элементов поставлено в очередь. Здесь будет ограничение, поскольку ThreadPool относительно медленно раскручивает дополнительные потоки. При длительной перегрузке ваша система будет стонать. Как я уже сказал, лучший способ приблизиться к этому — использовать асинхронный ввод-вывод.

person spender    schedule 26.01.2010

Вы можете помещать задачи в потоки, когда хотите, чтобы они выполнялись:

public abstract class MyTask {
    public abstract void DoWork();
}


// ...

public void SomeTaskStarter()
{
    MyTask task = SomeFactoryMethodToCreateATaskInstance();

    new Thread(new ThreadStart(task.DoWork)).Start();
}

MyTask — это абстрактный класс, представляющий задачу для выполнения, и он определяет метод DoWork(), который будет делать то, что вы хотите. SomeFactoryMethodToCreateATaskInstance() создаст конкретный экземпляр задачи, и все, что вам нужно сделать, это написать DoWork(), чтобы сделать то, что вам нужно:

public class Twitterer : MyTask
{
    private string _tweet;
    public Twitterer(string tweet)
    {
        _tweet = tweet;
    }
    public override DoWork()
    {
        TwitterApi api = new TwitterApi(); // whatever
        api.PostTweet(tweet);
    }
}

Вы наверняка захотите выполнить какое-то действие по завершению задачи. Что бы вы ни делали, процедура завершения задачи должна быть потокобезопасной и, вероятно, должна вызываться через BeginInvoke()/EndInvoke(), если вам нужно выполнить какую-либо работу с пользовательским интерфейсом.

SomeTaskStarter() лучше всего вызывать из службы Windows и, скорее всего, будет содержать аргумент с информацией о том, какую задачу следует запустить и т. д.

person plinth    schedule 26.01.2010