2017-01-15 4 views
0

Я хочу выполнить .exe каждое утро в 4:00 утра. Я сделал это, используя следующий код.Как выполнять несколько задач в бесконечном цикле при использовании с thread.sleep

while (true) 
    { 
     var now = DateTime.Now; 
     var schedule = new DateTime(now.Year, now.Month, now.Day, 4, 00, 00); 
     if (schedule < now) schedule = schedule.AddDays(1); 

     Thread.Sleep(schedule.Subtract(now)); 

     Process.Start("sample.exe"); 
    } 

Теперь я хочу, чтобы выполнить еще одну задачи, такие как удаление папки и подпапки каждую ночь в 1:00 AM. Таким образом, для удаления я буду использовать код как

Directory.Delete(folder_path, recursive: true); 

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

+0

Вы вынуждены использовать Thread.Sleep или вы не нашли классы Timer? – rene

+0

Если вы можете использовать Задачи, можете использовать [Задержка] (http://stackoverflow.com/questions/13429707/how-to-get-awaitable-thread-sleep?rq=1) и иметь несколько Заданий со своим собственным Задержкой. – rene

+0

Я чувствую, что это утверждение проще – peter

ответ

1

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

Итак, если вы делаете это так, вам просто нужно больше потоков.

var scheduleLoopAction = new Action<int, int, string>((int hour, int minute, string processName) => 
{ 
    while (true) 
    { 
     var now = DateTime.Now; 
     var schedule = new DateTime(now.Year, now.Month, now.Day, hour, minute, 00); 
     if (schedule < now) schedule = schedule.AddDays(1); 

     System.Threading.Thread.Sleep(schedule.Subtract(now)); 

     System.Diagnostics.Process.Start(processName); 
    } 
}); 

((new System.Threading.Thread(() => { scheduleLoopAction(4, 0, "sample.exe"); }))).Start(); 
((new System.Threading.Thread(() => { scheduleLoopAction(1, 0, "sample2.exe"); }))).Start(); 

Это, вероятно, не лучший способ достижения цели, но я понял, что вы бы хотели что-то вроде того, что было в этом вопросе.

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

((new System.Threading.Thread(() => { scheduleLoopAction(4, 0, "sample.exe"); }))).Start(); 
scheduleLoopAction(1, 0, "sample2.exe"); // Runs in current thread 
4

Вы не должны использовать Thread.Sleep для синхронизации. Старайтесь избегать Thread.Sleep. Вы можете прервать спящий режим, только если вы прервите этот поток. Лучшим способом будет ManualResetEvent.Wait(), который можно прервать, установив его.


Мой совет есть, использовать таймер:

Создать таймер, который проверяет список заданий. Добавьте следующий раз для выполнения задания. Таймер не блокирует MainThread, поэтому вы можете безопасно прекратить действие приложения. Вы можете проверять задания (интервал) каждую минуту или даже выше.

PSEUDO !!

class MyJob 
{ 
    public DateTime ExecuteTime { get; set; } 
    public Action Action { get; set; } 
} 

List<MyJob> Jobs = new List<MyJob>(); 

public void TimerCallback(object sender, EventArgs e) 
{ 
    foreach (var job in Jobs) 
    { 
     if (job.ExecuteTime <= DateTime.Now) 
     { 
      try 
      { 
       job.Action(); 
      } 
      catch(Exception exception) 
      { 
       // log the exception.. 
      } 
      finally 
      { 
       job.ExecuteTime = job.ExecuteTime.Add(TimeSpan.FromDays(1)); 
      } 
     } 
    } 
} 

// this AddJob checks if the first execute should be today or tomorrow 
public void AddJob(TimeSpan executeOn, Action action) 
{ 
    var now = DateTime.Now; 

    var firstExec = new DateTime(now.Year, now.Month, now.Day, 4, 0, 0); 

    if (firstExec < now) // time for today is already passed, next day.. 
     firstExec = firstExec.Add(TimeSpan.FromDays(1)); 

    Jobs.Add(new MyJob { ExecuteTime = firstExec, Action = action }); 
} 

public void Add() 
{ 
    // Add the jobs. 
    AddJob(new TimeSpan(4, 0, 0), RunMyJob); 
    AddJob(new TimeSpan(5, 0, 0), RunMyJob2); 
} 

public void RunMyJob() 
{ 
    // delete or move, whatever... 
} 

public void RunMyJob2() 
{ 
    // delete or move, whatever... 
} 
+0

Я отметил свой вопрос как консольное приложение, позвольте мне посмотреть, что это будет работать – peter

+0

@rene, как говорится, это псевдо. Он может использовать таймер для потоковой передачи: посмотрите здесь: [Как добавить таймер в консольное приложение C#] (http://stackoverflow.com/questions/186084/how-do-you-add-a-timer-to- ас-диез-консольное приложение). Я просто привел пример. Он должен сделать реализацию ;-) –

+0

@peter посмотреть ссылку в предыдущем комментарии –

2

Если все, что вы делаете это планирование один EXE-файл, вы можете использовать планировщик задач Windows - это намного проще, чем пытаться сделать это самостоятельно. Если вам нужно выполнить несколько заданий в несколько раз, вы можете создать несколько .exe. (Извините за краткий, я пишу это по телефону).

2

Для этого я использовал бы реактивную платформу Microsoft (NuGet «System.Reactive»).

Вы можете написать этот удобный вспомогательный метод:

public IDisposable ScheduleDaily(TimeSpan when, Action what) 
{ 
    var now = DateTime.Now; 
    var schedule = now.Date.Add(when); 
    if (schedule < now) 
    { 
     schedule = schedule.AddDays(1.0); 
    } 

    return 
     Observable 
      .Timer(schedule, TimeSpan.FromDays(1.0)) 
      .Subscribe(_ => what()); 
} 

Чтобы назвать это просто сделать это:

IDisposable runSample = ScheduleDaily(TimeSpan.FromHours(4.0), 
    () => Process.Start("sample.exe")); 

IDisposable deleteFolders = ScheduleDaily(TimeSpan.FromHours(1.0), 
    () => Directory.Delete(folder_path, recursive: true)); 

ScheduleDaily возвращает удобный IDisposable, что вы можете .Dispose(), чтобы остановить таймер.

Ничего и не требуется. Очень просто.

 Смежные вопросы

  • Нет связанных вопросов^_^