Я мало знаю о деталях низкого уровня; но, учитывая, что в 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 не поддерживается.
Система. Таймеры. Таймер . Если Вы захотите работать в определенные времена дня, необходимо будет выяснить, какой длины это до следующего раза и установило это как интервал.
Это - просто основная идея. В зависимости от того, насколько точный необходимо быть Вами, может сделать больше.
int minutes = DateTime.Now.Minute;
int adjust = 10 - (minutes % 10);
timer.Interval = adjust * 60 * 1000;
Можно найти справку с Quartz.net http://quartznet.sourceforge.net/
Вот пример легкой системы с помощью синхронизации потока и асинхронного вызова.
я знаю, что существуют некоторые оборотные стороны, но мне нравится использовать это вместо таймера при начинании длительного процесса (как 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);
}
}
Система. Windows. Формы. Таймер (или Система. Таймеры. Таймер)
, но так как теперь Вы говорите Вас, не хотят использовать Таймеры, можно работать, легкий процесс ожидания на другом потоке (проверьте время, спите несколько секунд, проверьте время снова...), или сделайте компонент, который генерирует событие (использующий легкий процесс ожидания) на определенных запланированных временах или интервалах
Другой стратегией для этого будет запись ПОСЛЕДНЕГО ВРЕМЕНИ, которое процесс был запущен и определите, истек ли желаемый интервал с того времени. В этой стратегии Вы бы закодировали событие, чтобы оно сработало, если прошедшее время равно ИЛИ БОЛЬШЕ, чем желаемый интервал. Таким образом, вы можете обрабатывать случаи, когда длинные промежутки (например, один раз в день) могут быть пропущены, если компьютер по какой-то причине не работает.
Так, например:
Очевидно, что для восстановления после сбоя системы вам нужно будет хранить lastRunDateTime в файле или базе данных где-то так, программа могла начать с того места, на котором остановилась при восстановлении.