Останавливать ли таймер при выходе из функции или сборщик мусора о нём позаботится?

137
06 января 2020, 06:20

Я использую Stopwatch таймер для засекания времени выполнения участков кода в функциях моих проектов. По-хорошему, перед выходом из функции, в которой я использовал таймер, я должен его остановить. Но иногда в функции очень много мест выхода из функции, и не очень удобно останавливать таймер перед каждым таким return-ом. Вопрос - чревато ли это какими-то осложнениями - выйти из функции и не остановить таймер, или это не важно, т.к. локальный экземпляр таймера будет уничтожен (а может и нет) сборщиком мусора при выходе из функции?

Answer 1

Это обычный класс и судьба его за пределами области видимости переменной совершенно обычная.

Никаких осложнений типа "вдруг не остановив таймер собьются другие часы", "отвалится коннект к базе данных" или "произойдёт атомный взрыв" не будет - можете посмотреть декомпилированный исходник и глянуть код, этот класс даже не реализует IDisposable, так что сложностей с пониманием никаких нет.

// Decompiled with JetBrains decompiler
// Type: System.Diagnostics.Stopwatch
// Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 988FA076-10C9-4365-AE6D-295A6AA379FE
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.dll
using Microsoft.Win32;
namespace System.Diagnostics
{
  /// <summary>Provides a set of methods and properties that you can use to accurately measure elapsed time.To browse the .NET Framework source code for this type, see the Reference Source.</summary>
  [__DynamicallyInvokable]
  public class Stopwatch
  {
    private const long TicksPerMillisecond = 10000;
    private const long TicksPerSecond = 10000000;
    private long elapsed;
    private long startTimeStamp;
    private bool isRunning;
    /// <summary>Gets the frequency of the timer as the number of ticks per second. This field is read-only.</summary>
    [__DynamicallyInvokable]
    public static readonly long Frequency;
    /// <summary>Indicates whether the timer is based on a high-resolution performance counter. This field is read-only.</summary>
    [__DynamicallyInvokable]
    public static readonly bool IsHighResolution;
    private static readonly double tickFrequency;
    static Stopwatch()
    {
      if (!SafeNativeMethods.QueryPerformanceFrequency(out Stopwatch.Frequency))
      {
        Stopwatch.IsHighResolution = false;
        Stopwatch.Frequency = 10000000L;
        Stopwatch.tickFrequency = 1.0;
      }
      else
      {
        Stopwatch.IsHighResolution = true;
        Stopwatch.tickFrequency = 10000000.0;
        Stopwatch.tickFrequency /= (double) Stopwatch.Frequency;
      }
    }
    /// <summary>Initializes a new instance of the <see cref="T:System.Diagnostics.Stopwatch" /> class.</summary>
    [__DynamicallyInvokable]
    public Stopwatch()
    {
      this.Reset();
    }
    /// <summary>Starts, or resumes, measuring elapsed time for an interval.</summary>
    [__DynamicallyInvokable]
    public void Start()
    {
      if (this.isRunning)
        return;
      this.startTimeStamp = Stopwatch.GetTimestamp();
      this.isRunning = true;
    }
    /// <summary>Initializes a new <see cref="T:System.Diagnostics.Stopwatch" /> instance, sets the elapsed time property to zero, and starts measuring elapsed time.</summary>
    /// <returns>A <see cref="T:System.Diagnostics.Stopwatch" /> that has just begun measuring elapsed time.</returns>
    [__DynamicallyInvokable]
    public static Stopwatch StartNew()
    {
      Stopwatch stopwatch = new Stopwatch();
      stopwatch.Start();
      return stopwatch;
    }
    /// <summary>Stops measuring elapsed time for an interval.</summary>
    [__DynamicallyInvokable]
    public void Stop()
    {
      if (!this.isRunning)
        return;
      this.elapsed += Stopwatch.GetTimestamp() - this.startTimeStamp;
      this.isRunning = false;
      if (this.elapsed >= 0L)
        return;
      this.elapsed = 0L;
    }
    /// <summary>Stops time interval measurement and resets the elapsed time to zero.</summary>
    [__DynamicallyInvokable]
    public void Reset()
    {
      this.elapsed = 0L;
      this.isRunning = false;
      this.startTimeStamp = 0L;
    }
    /// <summary>Stops time interval measurement, resets the elapsed time to zero, and starts measuring elapsed time.</summary>
    [__DynamicallyInvokable]
    public void Restart()
    {
      this.elapsed = 0L;
      this.startTimeStamp = Stopwatch.GetTimestamp();
      this.isRunning = true;
    }
    /// <summary>Gets a value indicating whether the <see cref="T:System.Diagnostics.Stopwatch" /> timer is running.</summary>
    /// <returns>
    /// <see langword="true" /> if the <see cref="T:System.Diagnostics.Stopwatch" /> instance is currently running and measuring elapsed time for an interval; otherwise, <see langword="false" />.</returns>
    [__DynamicallyInvokable]
    public bool IsRunning
    {
      [__DynamicallyInvokable] get
      {
        return this.isRunning;
      }
    }
    /// <summary>Gets the total elapsed time measured by the current instance.</summary>
    /// <returns>A read-only <see cref="T:System.TimeSpan" /> representing the total elapsed time measured by the current instance.</returns>
    [__DynamicallyInvokable]
    public TimeSpan Elapsed
    {
      [__DynamicallyInvokable] get
      {
        return new TimeSpan(this.GetElapsedDateTimeTicks());
      }
    }
    /// <summary>Gets the total elapsed time measured by the current instance, in milliseconds.</summary>
    /// <returns>A read-only long integer representing the total number of milliseconds measured by the current instance.</returns>
    [__DynamicallyInvokable]
    public long ElapsedMilliseconds
    {
      [__DynamicallyInvokable] get
      {
        return this.GetElapsedDateTimeTicks() / 10000L;
      }
    }
    /// <summary>Gets the total elapsed time measured by the current instance, in timer ticks.</summary>
    /// <returns>A read-only long integer representing the total number of timer ticks measured by the current instance.</returns>
    [__DynamicallyInvokable]
    public long ElapsedTicks
    {
      [__DynamicallyInvokable] get
      {
        return this.GetRawElapsedTicks();
      }
    }
    /// <summary>Gets the current number of ticks in the timer mechanism.</summary>
    /// <returns>A long integer representing the tick counter value of the underlying timer mechanism.</returns>
    [__DynamicallyInvokable]
    public static long GetTimestamp()
    {
      if (!Stopwatch.IsHighResolution)
        return DateTime.UtcNow.Ticks;
      long num = 0;
      SafeNativeMethods.QueryPerformanceCounter(out num);
      return num;
    }
    private long GetRawElapsedTicks()
    {
      long elapsed = this.elapsed;
      if (this.isRunning)
      {
        long num = Stopwatch.GetTimestamp() - this.startTimeStamp;
        elapsed += num;
      }
      return elapsed;
    }
    private long GetElapsedDateTimeTicks()
    {
      long rawElapsedTicks = this.GetRawElapsedTicks();
      if (Stopwatch.IsHighResolution)
        return (long) ((double) rawElapsedTicks * Stopwatch.tickFrequency);
      return rawElapsedTicks;
    }
  }
}

PS "Класс Stopwatch появился в .NET 2.0 и с тех по не претерпел ни одного изменения."

READ ALSO
Переключатель Switch в диалоговом окне

Переключатель Switch в диалоговом окне

есть диалоговое окно с Switch и TextView, хочу при переключении Switch отображать или прятать TextViewНиже приведенный код не работает, пробовал на переключение...

128
Где хранить пароль

Где хранить пароль

Пишу приложение aspnet core MVC

117
Как передать на принтер информацию о необходимости сшивать листы?

Как передать на принтер информацию о необходимости сшивать листы?

Есть Konica Minolta 554e, на ней размножаем документы (всего 38 документов)Часть из документов печатается в две страницы на листе, часть одностраничные,...

148
Response Ajax в laravel

Response Ajax в laravel

У меня есть страница, на которой три поляДанные в контроллер отправляются при помощи Ajax

133