2012-05-22 1 views
7

ich mein Projekt baue mit dem „Microsoft Minimal-Regeln“ Code-Analyse-Set und es gibt mir CA2000 auf dieser Methode:Warum verursacht diese Methode Code-Analyse Fehler CA2000: Rufen Sie Dispose()

private Timer InitializeTimer(double intervalInSeconds) 
{ 
    Timer timer = null; 

    try 
    { 
     timer = new Timer { Interval = intervalInSeconds * 1000, Enabled = true }; 
     timer.Elapsed += timer_Elapsed; 
     timer.Start(); 
    } 
    catch 
    { 
     if (timer != null) 
     { 
      timer.Dispose(); 
     } 
    } 
    return timer; 
} 

Diese Methode erstellt nur eine neue System.Timers.Timer aus einem Intervall in Sekunden. Ich habe drei solche Timer laufen (eine für jede Sekunde, eine jede Minute und jede halbe Stunde). Vielleicht ist es besser, einen Timer zu haben und den Event-Handler zu überprüfen, ob eine Minute oder eine halbe Stunde vergangen ist, aber ich weiß nicht, das ist zu diesem Zeitpunkt einfacher, es ist Code geerbt und ich möchte nicht alles kaputt machen noch.

Diese Methode gibt mir das berüchtigte

Warning 21 CA2000 : Microsoft.Reliability : In method 'TimerManager.InitializeTimer(double)', call System.IDisposable.Dispose on object '<>g__initLocal0' before all references to it are out of scope. 

Jetzt bin ich Entsorgen im Fang Aufruf und dachte, dass dies ausreicht? Ich verfüge auch über alle Timer in der eigenen IDisposable-Implementierung der Klasse.

Was fehlt mir hier?

+4

die Objektinitialisierer Syntax herausnehmen - das ist, was die Warnung der Auslösung (da das Objekt vorhanden ist, gebaut, aber "timer" wird nicht zugewiesen, während der Initialisierer läuft. Ich versuche, die Dupefrage zu finden, die sich damit beschäftigt. –

+1

mögliches Duplikat von [Objektinitialisierer in using-block generiert Codeanalysewarnung CA2000] (http://stackoverflow.com/questions/3514902/object-initializers-in-using-block-generiert-code-analysis-warning-ca2000) –

+3

Nun, werfen Sie nicht die Initialisierersyntax für ein dummes Tool weg.Die Warnung ist gefälscht, da ist nichts zu entsorgen, bis Start() aufgerufen wird. Verschlucken von Ausnahmen und Zurückgeben eines entsorgten Objekts, jetzt * das * wäre etwas, über das man sich beschweren könnte. –

Antwort

2

Sie rufen nur Dispose im Falle einer Ausnahme (die Sie nie mit einem Catch-All-Block BTW behandeln sollten, aber das ist eine andere Geschichte). Im Ausnahmefall verfügen Sie nicht über das Objekt Timer.

Entweder einen finally Block hinzufügen und den Dispose dorthin verschieben, oder einen using Block verwenden.

+0

Da der Timer auf "keine Ausnahme" zurückgegeben wird, sollte das nicht in Ordnung sein? Oder besser: Warum sollte es * immer * entsorgt werden? –

+0

Okay, aber ich möchte, dass der Timer die Methode überlebt, da er einem Feld in meiner Klasse zugewiesen ist. Ich verteile meine Felder in der IDisposable-Implementierung. Mein Versuch-Fang war ein Versuch, die Warnung zu unterdrücken. – Davio

+0

@ pst Ja, das sollte OK sein, aber CodeAnalysis erkennt es möglicherweise nicht. Du könntest diesen bestimmten Vorfall dann unterdrücken. –

1

Die Warnung besagt, dass Sie ein Einwegobjekt erstellen und es nicht in allen Fällen entsorgen. Wenn Sie es ordnungsgemäß in einer anderen Methode entsorgen, können Sie diese Warnung sicher unterdrücken (Sie können das unter Verwendung der SuppressMessageAttribute) tun.

+0

Das mache ich in anderen Fällen (Unity's LifeTimeManager), wollte das aber zuerst überprüfen, bevor ich es hier mache. – Davio

+0

Ja, ich bekomme diese Warnung ziemlich oft mit lang laufenden Objekten wie Timern. Es ist nur da, um Sie darauf aufmerksam zu machen, dass Sie das Objekt irgendwo anders entsorgen müssen. –

1

Okay, ich bearbeitet es wie folgt aus:

private Timer InitializeTimer(double intervalInSeconds) 
    { 
     Timer tempTimer = null; 
     Timer timer; 
     try 
     { 
      tempTimer = new Timer(); 
      tempTimer.Interval = intervalInSeconds * 1000; 
      tempTimer.Enabled = true; 
      tempTimer.Elapsed += timer_Elapsed; 
      tempTimer.Start(); 
      timer = tempTimer; 
      tempTimer = null; 
     } 
     finally 
     { 
      if (tempTimer != null) 
      { 
       tempTimer.Dispose(); 
      } 
     } 
     return timer; 
    } 

Dies ist nach den CA2000 docs und es keine Warnung geben. Ich hatte übersehen, dass die Objektinitialisierersyntax ein temporäres Objekt erzeugt, das nicht entsorgt werden kann.

Danke, Jungs!

+0

Möglicherweise möchten Sie das schließlich zu einem Fang mit erneutem Wechsel ändern. Andernfalls werden Sie den Zeitgeber vor der Rückgabe aus der Methode entfernen, auch wenn keine Ausnahme ausgelöst wird. –

+0

@NicoleCalinoiu Es ist nur verfügbar, wenn der Temp nicht null ist und der Temp nur nicht null ist, wenn er nicht die letzte Zeile des try-Blocks erreicht hat, was bedeutet, dass eine Ausnahme ausgelöst wurde. Das geht nur darum herum, eine Ausnahme zu fangen und nachzuholen. – juharr

-1

Ich denke, es ist viel besser nutzen „können“ anstelle von „try/finally“ reference

private Timer InitializeTimer(double intervalInSeconds) 
{ 
    Timer timer; 
    using (var tempTimer = new Timer()) 
    { 
     tempTimer.Interval = intervalInSeconds * 1000; 
     tempTimer.Enabled = true; 
     tempTimer.Elapsed += timer_Elapsed; 
     tempTimer.Start(); 
     timer = tempTimer; 
    } 
    return timer; 
} 
Verwandte Themen