【问题标题】:Using IDisposable + timer to measure elapsed time使用 IDisposable + timer 来测量经过的时间
【发布时间】:2019-04-12 22:18:34
【问题描述】:

我有一些代码可以做很多工作。它在足够长的时间内完成了足够多的工作,以至于我们通常不关心精确的准确性(即到毫秒),但是关闭超过一分钟是没有用的。我们有一个存储过程,我们调用它来记录任务的开始和任务的结束。现在我们有很多这样的代码:

Logger.LogTaskStart(taskName);
// do stuff
Logger.LogTaskEnd(taskName);

这两种方法保存元数据的地方,最终通过上述存储过程持久化。我们也有一些地方有时可能会记录计时信息,但并非总是如此,这要么是噪音太大,要么通常没有问题。

if (debug) Logger.LogTaskStart(taskName);
// do stuff
if (debug) Logger.LogTaskEnd(taskName);

我们遇到过不匹配开始和结束的问题,或者我们只将一个放在调试标志下,等等。我们考虑创建一个非常简单的记录器类来实现 IDisposable 来为我们做这件事,例如我们只是这样做(假设构造函数启动计时器 RAII 样式,并且 Dispose 停止它)

using (new Logger(taskName, debug))
{
    // Do stuff
}

据我们所知,这应该只是编译成大约这样:

Logger loggerThing = null;
try
{
    loggerThing = new Logger(taskName, debug);
    // Do stuff
}
finally
{
    loggerThing?.Dispose();
}

因此,将其用于具有足够粒度的大型任务似乎相当安全,可以说“运行了合理的时间”或“运行速度比正常快/慢”。我们是对的吗?

通过阅读,我找到了以下文章、代码示例和 SO Q&A。我们显然不是唯一想到这个或类似的东西的人,但似乎没有人对“我们认为 Dispose 将被调用多及时,以及它的可靠性如何”这个问题给出明确而明确的答案。那会是什么计时结果?”鉴于下面的第一篇文章,关于 using 如何只是语法糖,我们倾向于认为是这种情况。

【问题讨论】:

  • 很明显,您有理由不信任您链接到的问题中的answer...但是为什么呢?究竟缺少什么来向您澄清Dispose 是如何被using 调用的?
  • 及时是什么意思? Dispose 将在 using 块的末尾被调用。

标签: c# idisposable stopwatch


【解决方案1】:

在 using 语句中的代码之后立即调用 Dispose 方法。为了证实这一点,我们可以看一下从 using 语句生成的 IL:

以下简单示例:

    class Program
    {
        static void Main()
        {
            using (new TestClass())
            {
                Console.WriteLine("Do work");

            }
        }
    }

    class TestClass : IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine("disposed");
        }
    }


产生以下 IL。

Program.Main:
IL_0000:  nop         
IL_0001:  newobj      UserQuery+TestClass..ctor
IL_0006:  stloc.0     
IL_0007:  nop         
IL_0008:  ldstr       "Do work"
IL_000D:  call        System.Console.WriteLine
IL_0012:  nop         
IL_0013:  nop         
IL_0014:  leave.s     IL_0021
IL_0016:  ldloc.0     
IL_0017:  brfalse.s   IL_0020
IL_0019:  ldloc.0     
IL_001A:  callvirt    System.IDisposable.Dispose
IL_001F:  nop         
IL_0020:  endfinally  
IL_0021:  ret         

Program..ctor:
IL_0000:  ldarg.0     
IL_0001:  call        System.Object..ctor
IL_0006:  nop         
IL_0007:  ret         

TestClass.Dispose:
IL_0000:  nop         
IL_0001:  ldstr       "disposed"
IL_0006:  call        System.Console.WriteLine
IL_000B:  nop         
IL_000C:  ret         

TestClass..ctor:
IL_0000:  ldarg.0     
IL_0001:  call        System.Object..ctor
IL_0006:  nop         
IL_0007:  ret         

这里我们可以看到在 using 语句中的代码之后立即调用了 dispose 方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-06
    • 2021-03-01
    • 2017-07-13
    • 1970-01-01
    • 1970-01-01
    • 2019-05-08
    • 1970-01-01
    • 2013-05-19
    相关资源
    最近更新 更多