Как Вы изменили бы мой Процесс биения, записанный в C#?

Я смотрю на реализацию процесса "Heartbeat", чтобы сделать много повторных задач очистки в течение дня.

Это походило на хороший шанс использовать Шаблон "команда", таким образом, у меня есть интерфейс, который похож:

   public interface ICommand
   {
       void Execute();
       bool IsReady();
   }

Я затем создал несколько задач, что я хочу быть выполненным. Вот основной пример:

public class ProcessFilesCommand : ICommand
{
    private int secondsDelay;
    private DateTime? lastRunTime;

    public ProcessFilesCommand(int secondsDelay)
    {
        this.secondsDelay = secondsDelay;
    }

    public void Execute()
    {
        Console.WriteLine("Processing Pending Files...");
        Thread.Sleep(5000); // Simulate long running task
        lastRunTime = DateTime.Now;
    }

    public bool IsReady()
    {
        if (lastRunTime == null) return true;

        TimeSpan timeSinceLastRun = DateTime.Now.Subtract(lastRunTime.Value);
        return (timeSinceLastRun.TotalSeconds > secondsDelay);
    }

}

Наконец, мое консольное приложение работает в этом цикле, ища ожидающие задачи, чтобы добавить к ThreadPool:

class Program
{
    static void Main(string[] args)
    {

        bool running = true;

        Queue<ICommand> taskList = new Queue<ICommand>();
        taskList.Enqueue(new ProcessFilesCommand(60)); // 1 minute interval
        taskList.Enqueue(new DeleteOrphanedFilesCommand(300)); // 5 minute interval

        while (running)
        {
            ICommand currentTask = taskList.Dequeue();
            if (currentTask.IsReady())
            {
                ThreadPool.QueueUserWorkItem(t => currentTask.Execute());
            }
            taskList.Enqueue(currentTask);
            Thread.Sleep(100);
        }

    }
}

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

Это походит на дизайн "OK" для того, что я хочу сделать? Есть ли что-нибудь, что Вы изменили бы?

8
задан mmcdole 27 January 2010 в 02:29
поделиться

5 ответов

Это отличное начало. В последнее время мы сделали кучу подобных вещей, так что я могу предложить несколько предложений.

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

  2. Пусть Main() рутина отслеживать, когда вещи запущены и как долго каждый из них работает дальше. Вместо того, чтобы говорить "да, я готов" или "нет, я не готов", что будет одинаково для каждой команды, просто используйте поля LastRun и Interval, которые Main() может использовать для определения того, когда каждая команда должна быть выполнена.

  3. Не используйте очередь. Хотя это может показаться операцией типа очереди, так как каждая команда имеет свой интервал, на самом деле это не обычная очередь. Вместо этого поместите все команды в список, а затем отсортируйте список по кратчайшему времени для следующего запуска. Спите в потоке до тех пор, пока не понадобится первая команда для выполнения. Выполните эту команду. Отсортируйте список по следующей команде для выполнения. Спать. Повторить.

  4. Не используйте несколько потоков. Если интервал каждой команды составляет минуту или несколько минут, то, скорее всего, вообще не нужно использовать потоки. Вы можете все упростить, делая все в одном потоке.

  5. Обработка ошибок. Такие вещи требуют обширной обработки ошибок, чтобы проблема в одной команде не приводила к сбою всего цикла, и чтобы можно было отлаживать проблему, когда она возникает. Вы также можете решить, должна ли команда немедленно повторить ошибку, или подождать следующего запланированного запуска, или даже задержать его более чем обычно. Вы также можете не регистрировать ошибку в команде, если она происходит каждый раз (ошибка в команде, которая выполняется часто, может легко создать огромные лог-файлы).

10
ответ дан 5 December 2019 в 08:24
поделиться

Я бы сделал все ваши классы команд неизменяемыми , чтобы вам не приходилось беспокоиться об изменениях состояния.

2
ответ дан 5 December 2019 в 08:24
поделиться

Бег Переменная должна быть помечена как Волатильный , если его состояние будет изменено другим потоком.

Что касается пригодности, почему бы не просто использовать таймер?

0
ответ дан 5 December 2019 в 08:24
поделиться

Вместо того, чтобы писать все с нуля, вы можете выбрать сборку вашего приложения с использованием фреймворка, который будет обрабатывать все планирование и потоковую обработку за вас. Открытая библиотека NCron предназначена именно для этой цели и очень проста в использовании.

Определите свою работу следующим образом:

class MyFirstJob : CronJob
{
    public override void Execute()
    {
        // Put your logic here.
    }
}

И создайте основную точку входа для вашего приложения, включая настройку расписания следующим образом:

class Program
{
    static void Main(string[] args)
    {
        Bootstrap.Init(args, ServiceSetup);
    }

    static void ServiceSetup(SchedulingService service)
    {
        service.Hourly().Run<MyFirstJob>();
        service.Daily().Run<MySecondJob>();
    }
}

Это весь код, который вам понадобится написать, если вы решите пойти по этому пути. Вы также получаете возможность сделать более сложное планирование или инъекцию зависимости , если это необходимо, и протоколирование включено сразу же.

Отказ от ответственности: я ведущий программист на NCron, так что я могу быть немного предвзятым! ;-)

6
ответ дан 5 December 2019 в 08:24
поделиться

Теперь «Параллельные расширения» от Microsoft должны быть жизнеспособным вариантом для написания параллельного кода или выполнения любых задач, связанных с потоками. Он обеспечивает хорошую абстракцию поверх пула потоков и системных потоков, так что вам не нужно думать императивно, чтобы выполнить задачу.

На мой взгляд, рассмотрите возможность его использования. Кстати, ваш код чистый.

Спасибо.

2
ответ дан 5 December 2019 в 08:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: