Как я могу поднять событие каждый час (или определенный интервал времени каждый час) в .NET?

Я мало знаю о деталях низкого уровня; но, учитывая, что в python 2.6 API предлагает возможность ждать потоков и завершать процессы, как запустить процесс в отдельном потоке?

import subprocess, threading

class Command(object):
    def __init__(self, cmd):
        self.cmd = cmd
        self.process = None

    def run(self, timeout):
        def target():
            print 'Thread started'
            self.process = subprocess.Popen(self.cmd, shell=True)
            self.process.communicate()
            print 'Thread finished'

        thread = threading.Thread(target=target)
        thread.start()

        thread.join(timeout)
        if thread.is_alive():
            print 'Terminating process'
            self.process.terminate()
            thread.join()
        print self.process.returncode

command = Command("echo 'Process started'; sleep 2; echo 'Process finished'")
command.run(timeout=3)
command.run(timeout=1)

Вывод этого фрагмента на моей машине:

Thread started
Process started
Process finished
Thread finished
0
Thread started
Process started
Terminating process
Thread finished
-15

, где можно видеть, что при первом выполнении процесс завершился правильно (код возврата 0), а во втором - завершение процесса (код возврата -15).

Я не тестировал в окнах; но, помимо обновления команды примера, я думаю, что она должна работать, поскольку я не нашел в документации ничего, что говорит о том, что thread.join или process.terminate не поддерживается.

30
задан Jon Seigel 6 March 2010 в 04:42
поделиться

5 ответов

Система. Таймеры. Таймер . Если Вы захотите работать в определенные времена дня, необходимо будет выяснить, какой длины это до следующего раза и установило это как интервал.

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

int minutes = DateTime.Now.Minute;
int adjust = 10 - (minutes % 10);
timer.Interval = adjust * 60 * 1000;  
31
ответ дан Dan VanWinkle 6 March 2010 в 04:42
поделиться
  • 1
    При выполнении, поскольку администратор работал на меня. Windows 8.1 Сообщество VS 2017 – Chris Catignani 25 July 2017 в 22:56

Можно найти справку с Quartz.net http://quartznet.sourceforge.net/

11
ответ дан suhair 6 March 2010 в 04:42
поделиться
  • 1
    Кто сказал " Визуальный studio"? Вы сказали! вопрос не имеет никакого упоминания об этом – T.S. 8 December 2017 в 17:26

Вот пример легкой системы с помощью синхронизации потока и асинхронного вызова.

я знаю, что существуют некоторые оборотные стороны, но мне нравится использовать это вместо таймера при начинании длительного процесса (как schedualed серверные службы). Так как это работает встроенный в потоке таймера, Вы не должны волноваться об этом начинаемый снова перед, первоначальный вызов закончился. Это могло быть расширено вполне немного, чтобы заставить его использовать массив datetimes как триггерные времена или добавить еще некоторые способности к нему. Я уверен некоторые из Вас, парни там знают некоторые лучшие пути.

    public Form1()
    {
        InitializeComponent();

        //some fake data, obviously you would have your own.
        DateTime someStart = DateTime.Now.AddMinutes(1);
        TimeSpan someInterval = TimeSpan.FromMinutes(2);

        //sample call
        StartTimer(someStart,someInterval,doSomething);
    }

    //just a fake function to call
    private bool doSomething()
    {
        DialogResult keepGoing = MessageBox.Show("Hey, I did something! Keep Going?","Something!",MessageBoxButtons.YesNo);
        return (keepGoing == DialogResult.Yes);
    }

    //The following is the actual guts.. and can be transplanted to an actual class.
    private delegate void voidFunc<P1,P2,P3>(P1 p1,P2 p2,P3 p3);
    public void StartTimer(DateTime startTime, TimeSpan interval, Func<bool> action)
    {
        voidFunc<DateTime,TimeSpan,Func<bool>> Timer = TimedThread;
        Timer.BeginInvoke(startTime,interval,action,null,null);
    }

    private void TimedThread(DateTime startTime, TimeSpan interval, Func<bool> action)
    {
        bool keepRunning = true;
        DateTime NextExecute = startTime;
        while(keepRunning)
        {
            if (DateTime.Now > NextExecute)
            {
                keepRunning = action.Invoke();
                NextExecute = NextExecute.Add(interval);
            }
            //could parameterize resolution.
            Thread.Sleep(1000);
        }            
    }
4
ответ дан ExCodeCowboy 6 March 2010 в 04:42
поделиться
  • 1
    Я также должен был выполнить командную строку разработчика VS как администратор, когда я видел эту ошибку там. – melicent 29 January 2019 в 13:27

Система. Windows. Формы. Таймер (или Система. Таймеры. Таймер)

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

1
ответ дан Steven A. Lowe 6 March 2010 в 04:42
поделиться
  • 1
    Если Ваше развертывание сервиса с помощью Visual studio 2017 > > Командная строка Разработчика для VS 2017 > > installutil.exe Вы получаете эту ошибку, которая точно соответствует этому заголовку страниц, следовательно это - довольно хорошее место для помещения этого ответа (для пользователей Visual Studio). Когда я выполнил командную строку снова как администратор, она исправляет ошибку. – andrew pate 13 May 2018 в 09:01

Другой стратегией для этого будет запись ПОСЛЕДНЕГО ВРЕМЕНИ, которое процесс был запущен и определите, истек ли желаемый интервал с того времени. В этой стратегии Вы бы закодировали событие, чтобы оно сработало, если прошедшее время равно ИЛИ БОЛЬШЕ, чем желаемый интервал. Таким образом, вы можете обрабатывать случаи, когда длинные промежутки (например, один раз в день) могут быть пропущены, если компьютер по какой-то причине не работает.

Так, например:

  • lastRunDateTime = 5/2/2009 в 20:00
  • Я хочу запускать свой процесс каждые 24 часа.
  • В событии таймера проверьте, прошло ли 24 часа ИЛИ БОЛЬШЕ с момента последнего запуска процесса.
  • Если да, запустите процесс, обновите lastRunDateTime с помощью добавление к нему желаемого интервала (в данном случае 24 часа, но каким бы он ни был)

Очевидно, что для восстановления после сбоя системы вам нужно будет хранить lastRunDateTime в файле или базе данных где-то так, программа могла начать с того места, на котором остановилась при восстановлении.

2
ответ дан 28 November 2019 в 00:01
поделиться
Другие вопросы по тегам:

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