我有一些代码可以完成很多工作。它可以在足够长的时间内完成足够的工作,因此我们通常不关心精确的准确性(即毫秒),但是超过一分钟的时间将毫无用处。我们有一个存储过程,我们可以调用该存储过程来记录任务的开始和结束。现在,我们有很多看起来像这样的代码:
Logger.LogTaskStart(taskName);
// do stuff
Logger.LogTaskEnd(taskName);
这两个方法在其中保存元数据,最终通过上述存储过程将其保留下来。我们也有一些地方有时会记录计时信息,但并非总是b / c,这要么是太多的噪音,要么通常是没有问题的。
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。我们显然不是唯一想到这一点或类似观点的人,但似乎没有人对“我们能在多长时间内假定将要处置”以及“将有多可靠”这一问题给出了明确而明确的答案。计时结果是?”鉴于下面的第一篇文章,关于using
只是语法糖,我们倾向于认为是这种情况。
答案 0 :(得分:0)
在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方法。