2012-02-04 57 views
2

.NET中的定時器是否可以放棄而不調用Dispose()或Close()?是否可以安全放棄計時器

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事件中運行的代碼是否可以放棄。也許,不可能說出來。不要做任何事情,比如更新數據庫或寫入文件。 – 2012-02-04 15:55:59

+0

@Hans:實際上寫入文件確切地說會做什麼。這是主意。我想擴展日誌框架以允許使用計時器和隊列進行異步日誌記錄。但是我不希望測井網絡的用戶不必去處理,因爲沒有其他的記錄器類型需要這樣做。 – galford13x 2012-02-04 17:11:16

回答

1

管理員加爾福特,

是的,你可以創建你的應用是否即將退出例如,將觸發新的事件OnExit並在應用程序的主線程即將關閉時收聽事件。一旦完成,您可以創建事件邏輯並在OnExit事件中完成定時器,業務或清理邏輯。希望這可以幫助。

問候

+0

謝謝,我認爲這可能會解決問題。 – galford13x 2012-02-04 17:03:09

+0

我應該使用哪個OnExit事件處理程序? – galford13x 2012-02-04 17:53:40

+0

您可以附加或連接到如下所示的AppDomain進程退出事件, static void Main(string [] args) AppDomain.CurrentDomain.ProcessExit + = new EventHandler(Application_OnExit); //做一些工作 } 無效Application_OnExit(對象發件人,EventArgs的){ // 不定時清理等 } – 2012-02-04 22:15:57

1

如果不處置它明確地將垃圾收集器的終結隊列清理。雖然這是「安全的」,但你會遭受性能損失。最好處置你的計時器。

+0

有沒有辦法知道應用程序是否正在退出?我的目的是編寫一個將使用定時器定期執行某些操作的庫,但我不希望用戶被要求在庫中處理和清理任何內容。 – galford13x 2012-02-04 15:53:21

+0

這會導致什麼懲罰? – weston 2012-02-04 15:53:34

+0

@ galford13x爲什麼你不想讓用戶清理乾淨?這就是IDisposable模式的工作方式。任何需要釋放系統資源的類都應該通過它的終結器來完成,所以如果有人忘記處理一個對象,那麼你就不會陷入困境。 – roken 2012-02-04 15:58:24

0

垃圾收集將清除定時器,如果你不處理它。如果計時器處於.exe中,並且計時器結束時只會退出進程,則您不必擔心。如果你編寫一個定時器被引用的庫,你會想要處理它來釋放資源,以提高你的庫的效率。

0

調用Dispose()允許你管理的對象使用的非託管資源的清理垃圾收集之前決定清理被管理對象,在此期間操作的非託管資源也被清洗。

調用Dispose()通常關於內存使用優化,但是,在某些情況下,不調用Dispose()實際上會導致您的軟件無法正常工作。例如:由於以太網端口數量有限,在使用後不釋放它們可能會導致系統用盡網絡端口。這通常稱爲「TCP/IP端口耗盡」,並且當您不使用Dispose()對使用網絡資源的受管對象(例如WCF客戶端)時可能會發生。

作爲一般規則,當您不再需要任何類實現IDisposable的對象時調用Dispose()總是一個聰明的想法。 (或者在使用{}塊中使用它)。

在你提供的例子中,它看起來像你的計時器變量是靜態的,並綁定到主線程。它也好像你正在使用你的計時器到你的程序結束。所以在這個特定的情況下,這並不重要。

+0

提供的代碼是提供一個簡單的例子。然而,我明白你的觀點。在我的情況下,我有一個單獨的程序集提供日誌記錄功能。我想通過添加一個異步記錄器來擴展程序集。一般來說,大多數記錄器不需要像記錄框架中通常包含的特殊關閉代碼。我不想將這個要求添加到這個已經很好的簡單框架中。 – galford13x 2012-02-04 23:20:43

相關問題