为什么此方法导致代码分析错误CA2000:调用Dispose()

时间:2012-05-22 07:22:46

标签: c# .net timer code-analysis

我正在使用“Microsoft Minimal Rules”代码分析集构建我的项目,它给了我CA2000这个方法:

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;
}

此方法只是以秒为单位创建一个新的System.Timers.Timer。我有三个这样的计时器(每秒一个,每分钟一个,每半个小时一个)。也许最好有一个计时器并检查已过时的事件处理程序是否已经过了一分钟或半小时,但我不知道,此时这更容易,它是继承的代码,我不想破坏一切爱好。

这种方法给了我臭名昭着的

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.

现在我在捕获中调用Dispose并认为这就足够了?我也将所有计时器都放在了类自己的IDisposable实现中。

我在这里缺少什么?

4 个答案:

答案 0 :(得分:2)

只有在异常的情况下你才能调用Dispose(你永远不应该使用全能阻止BTW,但这是另一个故事)。如果没有例外,则不会丢弃Timer对象。

添加finally块并移动Dispose,或使用using块。

答案 1 :(得分:1)

警告告诉您正在创建一次性物体,并且不会在所有情况下都将其丢弃。如果您正在以其他方法正确处理它,那么您可以安全地禁止此警告(您可以使用SuppressMessageAttribute执行此操作。)

答案 2 :(得分:1)

好的,我这样编辑:

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;
    }

这是根据CA2000文档而不是发出警告。我忽略了这样一个事实:对象初始化器语法创建了一个可能无法处理的临时对象。

谢谢,伙计们!

答案 3 :(得分:-1)

我认为使用“使用”代替“尝试/最终”更好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;
}