2012-01-08 12 views
-1

Windowsサービスでn分ごとに関数を実行する必要があります。終了したら、もう一度やり直してください。関数が開始されていれば、終了するまで再開できません。当初、私はこのアイデアを持っていた:Cでタイマを実装する別の方法#

void function() 
{ 
    while(true) 
    { 
    if(!is_running) 
    { 
     function_to_be_repeated(); 
     is_running = false; 
    } 
    else 
    { 
     Thread.Sleep(some_time); // wait to start again 
    } 
    } 
} 

は、その後、私は、このhttp://www.albahari.com/threading/part3.aspxが見つかりました:

bool running = false; 

static void Main() 
    { 
    // First interval = 5000ms; subsequent intervals = 1000ms 
    Timer tmr = new Timer (function_to_be_repeated, "...", 5000, 1000); 
    Console.ReadLine();  
    tmr.Dispose();   // This both stops the timer and cleans up. 
    } 

    static void function_to_be_repeated(object data) 
    { 
     if(!running) 
     { 
     running = true; 
     // do some stuff... 

     running = false; 
     } 

    } 

をしかし、私は

をEnterキーを押したときにそれが停止し、より良い、それを実装するための別の方法はありますか?

+5

「しかし、Enterキーを押すと停止します」 - はい、これはコードの動作です。今質問がありましたか? –

+0

'Thread.Sleep'を使うのではなく、タイマーに' AutoResetEvent'を使う傾向があり、かなりうまくいきました。それが示唆された解決策であろうとなかろうと、私は言うことができませんが、それは私にとってより軽い解決策のようなものを提供します。 –

+2

.NETには、(異なる名前空間にある) 'Timer'という名前のクラスがあります。あなたはどちらを使っていますか? –

答えて

0

上記のコードはおそらくコンソールアプリケーションで実行されるため、ENTER(正確にはConsole.Readline()のため)を押した後に存在します。

ただし、Windowsサービスでこれが必要であることに言及しました。

Windowsサービスでは、通常、OnStart()OnStop()のメソッドをServiceBaseから上書きします。あなたのケースでは、サービスコードは次のようになります。

private Timer tmr; 

protected override void OnStart(string[] args) 
{ 
    tmr = new Timer (function_to_be_repeated, "...", 5000, 1000); 
} 

protected override void OnStop() 
{ 
    tmr.Dispose(); 
} 
1

私は、あなたがより良い実装を言及し、Windowsサービスに言及して、アプリを終了Enterキーとして問題が何であるか全く完全に確信していません。

では、コンソールでそれを実行していて、

do 
{ 

} 
while (!Console.ReadLine().Equals("exit", 
            StringComparison.InvariantCultureIgnoreCase) 
     ); 

代わりの

Console.ReadLine(); 

ような何かを行うことができ、それを殺すためにキーを入力したくない。まず場合、これはあなたのコンソールがすることを意味します終了時に入力してEnterキーを押すか、xボタンを押してプログラムを終了するか、プロセスを終了したときにのみ終了します。

より高度な実装については、これがベストプラクティスである場合、私はわからないが、これは私がポーリングスレッド実装を使用して、それを行うだろうかです:

class Poll : IDisposable 
{ 
    private TimeSpan polledSpan; 
    WaitHandle[] handles = new WaitHandle[2]; 
    ManualResetEvent exit = new ManualResetEvent(false); 
    Thread thread; 
    public Poll(int polledTime) 
    { 
     polledSpan = new TimeSpan(0, 0, polledTime); 
     thread = new Thread(new ThreadStart(Start)); 
     thread.Start(); 
    } 

    private void Start() 
    {    
     AutoResetEvent reset = new AutoResetEvent(false); 
     handles[0] = reset; 
     handles[1] = exit; 
     bool run = true; 
     while (run) 
     {     
      int result = WaitHandle.WaitAny(handles, 
              (int)polledSpan.TotalMilliseconds, 
              false); 

      switch(result) 
      { 
       case WaitHandle.WaitTimeout: 
        run = StuffToDo(); 
        break; 
       case 1: 
       case 0: 
        run = false; 
        break; 
      }     
     }    
    } 

    private bool StuffToDo() 
    { 
     try 
     { 
      Console.WriteLine("Test"); 
      return true; 
     } 
     catch 
     { 
      return false; 
     } 
    } 

    public void Dispose() 
    { 
     exit.Set(); 
     if (thread != null) 
     { 
      thread.Join(10000); 
     } 
     exit = null; 
     handles = null; 
    } 
} 

とmainメソッドで

Poll p = new Poll(1); 
do 
{ 

} 
while (!Console.ReadLine().Equals("exit", 
            StringComparison.InvariantCultureIgnoreCase)); 
p.Dispose(); 
0

私はそれがあなたに問題を抱えているかどうかはわかりませんが、ここでは実際には自分自身とparallellで実行されないようにタイマーを使用する例があります(System.Threading.Timerはデフォルトでは実行しません) )。

また、Windowsサービスで実行する場合は、タイマーの作成をstartメソッドに移動し、タイマーインスタンスを停止してプロパティ内に保持してください。あなたがしたい場合は、次の目盛りまでの時間は、現在の1があなたには、いくつかのタイミングを追加し、「ついに」内のコードを変更する必要がありますかかった時間によって影響されること

class Program 
{ 
    static void Main(string[] args) 
    { 
     var timeBetweenTicks = (long) TimeSpan.FromSeconds(1).TotalMilliseconds; 
     System.Threading.Timer timer = null; 
     Action onTick =() => 
      { 
       timer.Change(Timeout.Infinite, Timeout.Infinite); 
       try 
       { 
        //Work on tick goes here 
        Console.WriteLine(DateTime.Now); 
       } 
       finally 
       { 
        timer.Change(timeBetweenTicks, timeBetweenTicks); 
       } 
      }; 
     using (timer = new System.Threading.Timer(_ => onTick(), null, 0, timeBetweenTicks)) 
     { 
      Console.ReadKey(); 
     } 
    } 
} 

は注意してください。

関連する問題