c# - 使用 IDisposable + timer 来测量经过的时间
问题描述
我有一些代码可以做很多工作。它在足够长的时间内完成了足够的工作,我们通常不关心精确的准确性(即到毫秒),但是超过一分钟是没有用的。我们有一个存储过程,我们调用它来记录任务的开始和任务的结束。现在我们有很多看起来像这样的代码:
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。我们显然不是唯一想到这个或类似的东西的人,但似乎没有人对“我们认为 Dispose 将被调用多及时,以及将如何可靠那会是什么计时结果?” 鉴于下面的第一篇文章,关于如何using
只是语法糖,我们倾向于认为是这种情况。
解决方案
在 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 方法。
推荐阅读
- javascript - JavaScript - 如何从另一个函数访问变量?
- r - 代表错误:尝试复制“闭包”类型的对象(if 语句中的箱线图)
- android - Android ConstraintLayout内的按钮拒绝显示以水平方向居中的多字符文本
- security - 路径攻击的用户名和密码应该是什么
- c# - C# - 在一个方法中,我怎样才能有 2 个参数是一个?
- sql - 具有各自值的多列到行
- kubernetes - 如何在helm中设置环境变量?
- javascript - 暂停脚本以获取按钮输入
- dependencies - shadow-cljs 没有解决依赖关系
- javascript - 使用 NodeJS 和 MySQL,await/async 函数有时不等待查询完成