2012-02-04 9 views
2

Dispose()またはClose()を呼び出さずに.NETのタイマーを放棄しても安全ですか?タイマを安全に放棄できますか?

static System.Timers.Timer timer = new Timer(); 

void Main() 
{ 
    timer.Elapsed += LogTimer_Elapsed(object, System.Timers.ElapsedEventArgs); 
    timer.Start(); 
    Thread.Sleep(10000); // Simulate doing something on main thread 
} 

static void LogTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
{ 
    DoStuff(); 
} 

誰でもこの解決策に問題がありますか?あなたはそれを処分していない場合は

static QueueLogger() 
{ 
    LogQueue = new Queue<KeyValuePair<Logger, LogEntry>>(50); 
    LogTimer = new Timer(); 
    LogTimer.Elapsed +=new System.Timers.ElapsedEventHandler(LogTimer_Elapsed); 
    AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit); 
} 

static void CurrentDomain_ProcessExit(object sender, EventArgs e) 
{ 
    LogTimer.Stop(); 
    LogTimer.Dispose(); 
    LogTimer_Elapsed(sender, null); // This is to process any remaining messages in the queue 
} 

static void LogTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
{ 
    lock (_locker) 
    { 
     while (LogQueue.Count > 0) 
     { 
      var queuedLogger = LogQueue.Dequeue(); 
      try 
      { 
       if (e != null) queuedLogger.Value.Message += " From " + sender.ToString(); 
       queuedLogger.Key.Log(queuedLogger.Value); 
      } 
      catch (Exception ex) 
      { 
       OnLoggingError(queuedLogger.Key, "Async Logging error", ex); 
      } 
     } 
    } 
} 
+2

タイマーは問題ありません。本当の問題は、Elapsedイベントで実行するコードが、プロセスが終了したときに中止するのが安全かどうかです。多分、話すことは不可能です。 dbaseを更新するか、ファイルに書き込むようなことはしないでください。 –

+0

@ハンス:実際にファイルへの書き込みは、まさに実行されるものです。ここに考えがあります。私はタイマーとキューを使って非同期ロギングを可能にするロギングフレームワークを拡張したかったのです。しかし、私は、ロギングネットワークのユーザが、他のロガータイプのどれもこれを必要としないので、処分に気を使わなければならないことを望んでいませんでした。 – galford13x

答えて

1

Galford、

はい、あなたはあなたのアプリケーションは、例えば終了しようとしている場合に発生する新しいイベントを作成することができますOnExitを実行し、アプリケーションのメインスレッドが終了しようとしているときにイベントを待ち受けます。それが完了すると、イベントロジックを作成し、タイマー、ビジネス、またはOnExitイベントでロジックをクリーンアップすることができます。お役に立てれば。ガベージコレクタは、クリーンアップにアンマネージリソースも掃除されている動作中の管理対象オブジェクトを、決定する前のDispose()を呼び出す

よろしく

+0

ありがとうございます、これは問題を解決するかもしれないと思います。 – galford13x

+0

私は使用すべきOnExitイベントハンドラはどこにありますか?以下に示すよう – galford13x

+0

あなたは {AppDomain.CurrentDomain.ProcessExit + =新しいイベントハンドラ(Application_OnExit)、アプリケーションドメイン処理終了イベントまで 静的な無効メイン(文字列[] args)をアタッチまたはワイヤことができます。 //いくつかの作業 } 無効Application_OnExit(オブジェクト送信者、EventArgsのeを)やる { //タイマーなど } –

1

は明示的には、ガベージコレクタのファイナライザのキューにクリーンアップされます。これは「安全」ですが、パフォーマンス上のペナルティが発生します。タイマーを処分するのが最善です。 http://msdn.microsoft.com/en-us/library/system.threading.timer.aspxから

+0

アプリケーションが終了しているかどうかを知る方法はありますか?私の目的は、タイマーを使って定期的に何かを行うライブラリーを書くことですが、ライブラリー上の何かを処分してクリーンアップする必要はありません。 – galford13x

+0

どのような罰金がかかりますか? – weston

+0

@ galford13xなぜあなたは物事をきれいにしたいのですか?これがIDisposableパターンの仕組みです。システムリソースを解放する必要があるクラスは、ファイナライザを使用して行う必要があります。したがって、オブジェクトを処分するのを忘れてしまった場合は、ホーズを取得しないでください。 – roken

1

「タイマはもはや必要とされ、タイマーが保持しているリソースを解放するためにDisposeメソッドを使用します。」

タイマーをプログラムの最後まで実行したい場合は、それを心配する必要はありません。

0

ガベージコレクションでは、処理しないとタイマーがクリーンアップされます。タイマーが.exeにあり、タイマーが終了してもプロセスが終了する場合は、本当に心配する必要はありません。タイマーを参照するライブラリを作成する場合は、ライブラリーをより効率的にするためにリソースを解放する必要があります。

0

管理対象オブジェクトによって使用されているアンマネージリソースのクリーンアップを可能にします。

Dispose()の呼び出しは通常メモリ使用の最適化に関するものですが、Dispose()を呼び出さないと実際にソフトウェアが正しく機能しなくなることがあります。例:イーサネットポートの数が限られているため、使用後にそれらを解放しないと、システムがネットワークポートを使い果たす可能性があります。これは一般に「TCP/IPポートの枯渇」として知られており、ネットワークリソース(WCFクライアントなど)を使用する管理オブジェクトに対してDispose()を呼び出さないと発生する可能性があります。

一般に、IDisposableを実装するクラスを必要としないときには、Dispose()を呼び出すのが常に理想的です。 (または{}ブロックを使用してそれを使用する)。

あなたが指定した例では、タイマー変数が静的で、メインスレッドにバインドされているようです。あなたのプログラムの最後までタイマーを使用しているようです。したがって、この特定のケースでは、実際には関係ありません。

+0

提供されたコードは、簡単な例を提供することでした。私はあなたのポイントを参照してください。私の場合、私はロギング機能を提供する別のアセンブリを持っています。私は非同期ロガーを追加してアセンブリを拡張したかったのです。一般に、ほとんどのロガーは通常、ロギングフレームワークに含まれている特別なシャットダウンコードを必要としません。私は、この素敵なシンプルなフレームワークにこの要件を追加したくありませんでした。 – galford13x

関連する問題