2011-05-27 12 views
0

次のコードが与えられると、ユーザーがキーを押すまでタイマーはPrintTimer関数を1秒ごとに起動します。C# - Timerのインスタンスはいつ殺されますか?

質問1>タイマーはいつ停止するのですか? タイマーはデフォルトでバックグラウンドスレッドであるため、フォアグラウンドスレッドが終了した後に強制終了されます。

質問2>プログラムでスレッドを呼び出すスレッドを停止する方法はありますか。

class Program 
{ 
    // continue to call this function until the user presses a 
    // key to terminate the application 
    static void PrintTime(object state) 
    { 
     Console.WriteLine("Time is: {0}", 
     DateTime.Now.ToLongTimeString()); 
    } 
    static void Main(string[] args) 
    { 
     TimerCallback timeCB = new TimerCallback(PrintTime); 
     System.Threading.Timer t = new Timer(
      timeCB, 
      null, 
      0, 
      1000); 
     Console.WriteLine("Hit key to terminate..."); 
     Console.ReadLine(); 
    } 
} 

答えて

4

プログラムが終了した場合にのみ回答1

は今タイマーが停止されます。バックグラウンドスレッドを使用して実際にそこに座っているわけではありませんが、タイマーイベントが発生すると、バックグラウンドスレッドであるThreadPoolスレッドを介してコールバックが呼び出されます。タイマーを停止

回答2

は、どちらかと同じくらい簡単です:

t.Change(Timeout.Infinite, Timeout.Infinite); 

- または -

t.Dispose(); 

前者は、あなたが他とTimerを再起動することができますChangeを呼び出します。後者はTimerを完全にクリーンアップします。

その動作の詳細については、Timerクラスの「備考」セクションをits MSDN documentationにお読みください。たとえば、Disposeを呼び出した後でも技術的に受信できるスレッドプールへの通知コールバックは、Timerが既にキューに入れられている可能性があるため、Disposeのタイミングが厄介です。質問2については

1

Timer.Enabled財産とTimer.Close()方法を参照してください

更新:べき各オプション:私は、私も(falseに有効セット)Timer.Stop()方法

アップデートを言及している必要があり、完全性のために仮定利用される?

大まかに言えば、タイマーを取り除くか、もう一度使用する予定がないか、タイマーを一時停止していますが、ある時点で復活させる予定です(少なくとも、それを復活させることができる)。

タイマーを取り除く場合は、Dispose/Closeを実行する必要があります。 IDisposableを実装しているオブジェクトで終了したときに、うまく動作するプログラムが行うと思われる処理のため、少なくともDisposeを呼び出す必要があります。つまり、オブジェクトがIDisposableとCloseメソッドの両方を実装している場合、Closeは単に空きリソース以上の処理を行う可能性があるため、Closeメソッドを呼び出す方がよいと思います。例えば、バッファをフラッシュしたり、他のオブジェクト固有のことをするかもしれません。 CloseメソッドがDisposeを呼び出すと予想されます。理想的には、Closeのドキュメントでは、Disposeを呼び出すことを明示的に述べています(しかし、Timer :: Closeのドキュメントでは、そのことを説明していません)。

タイマーを一時的に一時停止して復活させるには、Enabledプロパティをfalseに設定してから、再度trueに設定します。または、Stop()を呼び出してからStart()を呼び出して復活させることもできます。手を離した私は、あるテクニックの優先度を他のものよりも優先しません。

私は、StopとStartが若干読みやすく、効率が多少低いと主張するかもしれないと思います。

+0

私は非常に多くの選択肢(Dispose、Close、Stop)を使用します。 -xx – q0987

1

Timerは使い捨てですので、Disposeに電話する必要があります。再利用したい場合はStopに電話することもできますが、周期的なコールバックを持つTimerクラスにバグがあり、それを破棄して新しいタイマーで開始することをお勧めします。

あなたが投稿したコードでは、タイマーのファイナライザが(技術的に)呼び出され、それを殺すようになるということが起こります。

1

タイマーは、finzalizerの実行によってクリーンアップされます。それはガラベージになって、実際にはrelease to debug modeから変化します。あなたがあなたのアプリケーションを終了するまで、それが停止することはありません、あなたのアプリケーションで

internal class Program 
{ 
    // continue to call this function until the user presses a 
    // key to terminate the application 
    private static void PrintTime(object state) 
    { 
     Console.WriteLine("Time is: {0}", 
          DateTime.Now.ToLongTimeString()); 
    } 

    private static void Main(string[] args) 
    { 
     TimerCallback timeCB = new TimerCallback(PrintTime); 
     Timer t = new Timer(
      timeCB, 
      null, 
      0, 
      1000); 

     WeakReference wk = new WeakReference(t); 
     PrintStatus(wk); 

     Console.WriteLine("Hit key to terminate..."); 
     Console.ReadLine(); 

     t = null; 
     PrintStatus(wk); 
    } 

    private static void PrintStatus(WeakReference wk) 
    { 
     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 
     Console.WriteLine("Is timer alive? " + wk.IsAlive); 
    } 
} 
+0

WeakReferenceの使い方は? --thx – q0987

+0

WeakReferenceでは、追跡して対処し、収集されたかどうかを基本的に問い合わせることができます。 http://msdn.microsoft.com/en-us/library/system.weakreference.aspx –

1

は、ここでは、弱い参照を使用して実行できるテストです。

プログラムで停止するには、使用しているタイマーによって異なります。

System.Timers.Timer 

System.Threading.Timer 

最初の場合は、Stopメソッドを呼び出すことができます。 2番目の場合は、Dispose()する必要があります。

メソッド内でタイマーを開始し、そのタイマーへの参照を保持しないと、ガーベジコレクションが取得されたときにタイマーが停止することに注意してください。

+1

私はOPを更新しました。それはSystem.Threading.Timerであることを意図していました。 -どうも – q0987

関連する問題