2011-08-12 4 views
1

System.Timers.Timerオブジェクトに問題があります。私は定期的な間隔でタスクを実行するためにタイマーオブジェクトを使用します。タイマーのコンストラクタでは、仕事をやっているメソッド(DoTimeCheck())を呼び出して、起動時にタスクが一度実行されるようにします。作業は(定期的に)BackgroundWorkerで行われます。System.Timers.Timer遅延がアプリケーションをハングする

私はこれでタイマーを呼び出す:

UpdaterTimer ut = UpdaterTimer.UpdaterTimerInstance; 

私の問題は、私は3分(アプリケーションの起動時に実行される1)でタスクの最初の実行を遅らせる必要があるということです。後続の実行(Elapsedイベント)は遅滞なく実行する必要があります。

System.Threading.Thread.Sleep(TimeToDelayFirstRunInMiliseconds); 

でも、アプリのUI(メインスレッド)が使用できなくなるため、これは失敗します。どのようにUIをぶら下げることなくDoTimeCheck()の最初の実行を延期できますか? タイマーのコードは以下の通りです。問題が明確な方法で提示されない場合は、私にお知らせください。私は編集します。前もって感謝します。

public sealed class UpdaterTimer : Timer 
{ 
    private static readonly UpdaterTimer _timer = new UpdaterTimer(); 
    public static UpdaterTimer UpdaterTimerInstance 
    { 
     get { return _timer; } 
    } 

    static UpdaterTimer() 
    { 
     _timer.AutoReset = true; 
     _timer.Interval = Utils.TimeBetweenChecksInMiliseconds; 
     _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed); 
     _timer.Start(); 
     DoTimeCheck(); 

    } 

    static void _timer_Elapsed(object sender, ElapsedEventArgs e) 
    { 
     DoTimeCheck(); 
    } 

    private static void DoTimeCheck() 
    { 
     //... work here 
    } 
} 
+0

それはクラス全体ですか?(ちょうどすべての静的メソッドを持つTimerから継承することに興味があります) –

+0

DoTimeCheck()内のコードとは別に、関連クラス全体がはいです。すべての統計は、ただ1つのタイマーが実行されることを確実にすることになっています - シングルトン。もちろん、これはSystem.Timers.Timer(私はnewbです)から継承する最善の方法ではないかもしれませんが、それまでのところ動作しています。 –

答えて

4

これを行う1つの方法は、タイマーインターバルに初期値(たとえば3分)を与えることです。その後、Elapsedイベントハンドラでは、その後に使用される通常の値に間隔を変更することができます。

_timer.Interval = Utils.InitialCheckInterval; 

static void _timer_Elapsed(object sender, ElapsedEventArgs e) 
{ 
    if (_timer.Interval == Utils.InitialCheckInterval) 
    { 
     _timer.Interval = Utils.RegularCheckInterval; 
    } 

    DoTimeCheck(); 
} 
+0

Utils.TimeBetween ...をUtils.RegularIntervalと交換したくないですか? – Chris

+0

そうは思わない - タイマーは初期値に設定されます。最初にInterval Elapsesを実行すると、定期的な間隔に変更されます。 –

+0

私はあなたとあなたのコメントの間で編集したと思うし、私は編集後に私のコメントだけを見たと思っています。しかし、はい、それは今よく見えます。 :) – Chris

0

あなたのUIには別のスレッドが必要ですが、現在はUIもスリープしています。チェックthis postを確認してください。

1

あなたがメイン/ GUIスレッドでSleep(TimeToDelayFirstRunInMiliseconds);を呼び出していることを(あなたがそのコードを示していませんでしたが)表示されますので、それはあなたのUIスレッドがハングアップする原因だものです。代わりに、最初の実行で3分遅れるようにタイマーを設定し、その後、すべての後続の実行に必要な頻度でタイマーを再実行します。

0

あなたはWinFormsのメインUIをロックしたことがない

のBackgroundWorkerを制御使用する必要があり、このような状況でのThread.sleep使用しないでください。そこにあなたのロジックを書くことができます。

ここでは例: http://www.knowdotnet.com/articles/backgroundworker.html

+0

ありがとう、私はすでに、すべての作業を行うメソッドのBackgroundWorkerを使用します。私はすでにBackgroundWorker内部でスリープメソッドを追加しようとしましたが、UIのハングアップは2回発生します。これは、各timer.Elapsed()イベントで遅延が発生し、最初の実行のみを遅延させる必要があることを意味します。 –

1

あなたはすでにそれはそう罰金タイマーを使用しています。他のタイマーを起動する前に別のタイマーを使って3分遅れてください。

timer = new Timer(); 
timer.AutoReset = false; 
timer.Interval = 3*60*1000; 
timer.Elapsed += startOtherTimerMethod; 
timer.Start(); 

編集:は、私は、これは非常にそれだけで1つのタイマー、余分なメソッドを使用し、タイマーという事実を利用しているので、彼のソリューションは、よりエレガントであることを除いて、ピーター・ケリーの答えと同じであることに注意してくださいラン間で変更可能です。あなたがこの答えを気に入ったら、彼を愛するでしょう。 ;-)

1

あなたのUIは同じスレッドに存在するので、スレッドをスリープ状態にするとUIがハングします。別のスレッドでタイマーを実行する必要があります。

+0

あなたのコメントをありがとう - 私は長い仕事をするためにBackgroundWorkerを使用します。それ以外は、それは私のための薄い氷であるため、私はマルチスレッドから遠ざかっています。私はマルチスレッドの理解はまだありません。 –

+1

ここでそれが必要になります。しかし、.NETでマルチスレッドを実行する安全な方法があるので、落胆しないでください。このリンクを見てください:http://msdn.microsoft.com/en-us/library/ms951089.aspx –

0

System.Threading.Timerを使用します。コンストラクタは、最初の実行の遅延とその後の実行の間隔のパラメータをとります。

関連する問題