2008-10-09 7 views
106

Только это - Как добавить таймер в консольное приложение C#? Было бы здорово, если бы вы могли предоставить примерное кодирование.Как добавить таймер в консольное приложение C#

+9

Предупреждение: ответы здесь имеют ошибка, объект Timer собирается собирать мусор. Ссылка на таймер должна храниться в статической переменной, чтобы обеспечить сохранение тикания. – 2014-12-14 21:45:47

ответ

91

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

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

Мы можем видеть это изменение в кодексе из той же книги CLR Via C# Third Ed.

using System; 
using System.Threading; 

public static class Program { 

    public static void Main() { 
     // Create a Timer object that knows to call our TimerCallback 
     // method once every 2000 milliseconds. 
     Timer t = new Timer(TimerCallback, null, 0, 2000); 
     // Wait for the user to hit <Enter> 
     Console.ReadLine(); 
    } 

    private static void TimerCallback(Object o) { 
     // Display the date/time when this method got called. 
     Console.WriteLine("In TimerCallback: " + DateTime.Now); 
     // Force a garbage collection to occur for this demo. 
     GC.Collect(); 
    } 
} 
60

Используйте класс System.Threading.Timer.

System.Windows.Forms.Timer предназначен в первую очередь для использования в одном потоке, обычно в потоке пользовательского интерфейса Windows Forms.

В начале разработки .NET Framework также появился класс System.Timers. Однако обычно рекомендуется использовать класс System.Threading.Timer, поскольку это всего лишь обертка вокруг System.Threading.Timer.

Также рекомендуется всегда использовать статический (совместно используемый в VB.NET) System.Threading.Timer, если вы разрабатываете службу Windows и требуете, чтобы таймер запускался периодически. Это позволит избежать возможной преждевременной сборки мусора вашего объекта таймера.

Вот пример таймера в консольном приложении:

using System; 
using System.Threading; 
public static class Program 
{ 
    public static void Main() 
    { 
     Console.WriteLine("Main thread: starting a timer"); 
     Timer t = new Timer(ComputeBoundOp, 5, 0, 2000); 
     Console.WriteLine("Main thread: Doing other work here..."); 
     Thread.Sleep(10000); // Simulating other work (10 seconds) 
     t.Dispose(); // Cancel the timer now 
    } 
    // This method's signature must match the TimerCallback delegate 
    private static void ComputeBoundOp(Object state) 
    { 
     // This method is executed by a thread pool thread 
     Console.WriteLine("In ComputeBoundOp: state={0}", state); 
     Thread.Sleep(1000); // Simulates other work (1 second) 
     // When this method returns, the thread goes back 
     // to the pool and waits for another task 
    } 
} 

Из книги CLR Via C# Джеффа Рихтера. Кстати, эта книга описывает обоснование трех типов таймеров в главе 23, настоятельно рекомендуется.

+0

Можете ли вы предоставить немного больше информации о фактическом кодировании? – 2008-10-09 06:12:21

+0

Использует ли пример из msdn для вас? http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx – 2008-10-09 06:15:59

+0

Эрик, я не пробовал, но не было бы необычным, если бы была проблема с ним. Я замечаю, что он также пытается сделать какую-то межпоточную синхронизацию, это всегда область, которая может быть сложной, чтобы получить право. Если вы можете избежать этого в своем дизайне, всегда разумно это делать. – Ash 2008-10-09 06:29:54

18

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

using System; 
    using System.Threading; 

    class TimerExample 
    { 
     static public void Tick(Object stateInfo) 
     { 
      Console.WriteLine("Tick: {0}", DateTime.Now.ToString("h:mm:ss")); 
     } 

     static void Main() 
     { 
      TimerCallback callback = new TimerCallback(Tick); 

      Console.WriteLine("Creating timer: {0}\n", 
          DateTime.Now.ToString("h:mm:ss")); 

      // create a one second timer tick 
      Timer stateTimer = new Timer(callback, null, 0, 1000); 

      // loop here forever 
      for (; ;) 
      { 
       // add a sleep for 100 mSec to reduce CPU usage 
       Thread.Sleep(100); 
      } 
     } 
    } 

А вот полученный результат:

c:\temp>timer.exe 
    Creating timer: 5:22:40 

    Tick: 5:22:40 
    Tick: 5:22:41 
    Tick: 5:22:42 
    Tick: 5:22:43 
    Tick: 5:22:44 
    Tick: 5:22:45 
    Tick: 5:22:46 
    Tick: 5:22:47 

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

+6

Функция for (;;) {} вызывает 100% -ное использование процессора. – 2012-12-21 16:36:05

4

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

private void ThreadLoop(object callback) 
{ 
    while(true) 
    { 
     ((Delegate) callback).DynamicInvoke(null); 
     Thread.Sleep(5000); 
    } 
} 

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

и использовать/запуска вы можете сделать:

Thread t = new Thread(new ParameterizedThreadStart(ThreadLoop)); 

t.Start((Action)CallBack); 

Ответный Ваш аннулируются метод без параметров, который вы хотите назвать в каждом интервале. Например:

private void CallBack() 
{ 
    //Do Something. 
} 
9

Или с помощью Rx, коротким и сладким:

static void Main() 
{ 
Observable.Interval(TimeSpan.FromSeconds(10)).Subscribe(t => Console.WriteLine("I am called... {0}", t)); 

for (; ;) { } 
} 
1

Вы также можете создавать свои собственные (если несчастна с доступными опциями).

Создание собственного решения Timer - довольно простой материал.

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

/// <summary> 
/// Internal timer for window.setTimeout() and window.setInterval(). 
/// This is to ensure that async calls always run on the same thread. 
/// </summary> 
public class Timer : IDisposable { 

    public void Tick() 
    { 
     if (Enabled && Environment.TickCount >= nextTick) 
     { 
      Callback.Invoke(this, null); 
      nextTick = Environment.TickCount + Interval; 
     } 
    } 

    private int nextTick = 0; 

    public void Start() 
    { 
     this.Enabled = true; 
     Interval = interval; 
    } 

    public void Stop() 
    { 
     this.Enabled = false; 
    } 

    public event EventHandler Callback; 

    public bool Enabled = false; 

    private int interval = 1000; 

    public int Interval 
    { 
     get { return interval; } 
     set { interval = value; nextTick = Environment.TickCount + interval; } 
    } 

    public void Dispose() 
    { 
     this.Callback = null; 
     this.Stop(); 
    } 

} 

Вы можете добавлять события следующим образом:

Timer timer = new Timer(); 
timer.Callback += delegate 
{ 
    if (once) { timer.Enabled = false; } 
    Callback.execute(callbackId, args); 
}; 
timer.Enabled = true; 
timer.Interval = ms; 
timer.Start(); 
Window.timers.Add(Environment.TickCount, timer); 

Чтобы убедиться, что таймер работает, Вы должны создать бесконечный цикл следующим образом:

while (true) { 
    // Create a new list in case a new timer 
    // is added/removed during a callback. 
    foreach (Timer timer in new List<Timer>(timers.Values)) 
    { 
     timer.Tick(); 
    } 
} 
10

Позволяет немного развлечься

using System; 
using System.Timers; 

namespace TimerExample 
{ 
    class Program 
    { 
     static Timer timer = new Timer(1000); 
     static int i = 10; 

     static void Main(string[] args) 
     {    
      timer.Elapsed+=timer_Elapsed; 
      timer.Start(); 
      Console.Read(); 
     } 

     private static void timer_Elapsed(object sender, ElapsedEventArgs e) 
     { 
      i--; 

      Console.Clear(); 
      Console.WriteLine("================================================="); 
      Console.WriteLine("     DIFFUSE THE BOMB"); 
      Console.WriteLine(""); 
      Console.WriteLine("    Time Remaining: " + i.ToString()); 
      Console.WriteLine("");   
      Console.WriteLine("================================================="); 

      if (i == 0) 
      { 
       Console.Clear(); 
       Console.WriteLine(""); 
       Console.WriteLine("=============================================="); 
       Console.WriteLine("   B O O O O O M M M M M ! ! ! !"); 
       Console.WriteLine(""); 
       Console.WriteLine("    G A M E O V E R"); 
       Console.WriteLine("=============================================="); 

       timer.Close(); 
       timer.Dispose(); 
      } 

      GC.Collect(); 
     } 
    } 
}