我编写了一个访问 ClosedXML 库的相对简单的控制台实用程序,以生成 Excel 电子表格。没有什么令人兴奋的,它应该运行得非常快。但是,当我启动它时,它会在控制台屏幕上停留约 8 秒,然后才会显示任何进度。
起初,我认为这是 ClosedXML 库需要一段时间来初始化。我启动了 dotTrace 并逐行进行性能分析,得到了一些奇怪的结果:
- 主线程 [14,352ms]
- 主要 [99.29% - 14,251 毫秒]
- 生成 [88.88% - 12,756ms]
- 11 个列出的调用总计 23.44% / 4,360ms
- get_Instance [6.78% - 974ms]
- Console.ReadLine [2.75% - 394ms]
- ResolvePolicy [0.82% - 118ms]
- 11个隐藏函数[0.01% - 1ms]
- 生成 [88.88% - 12,756ms]
- ResolvePolicy [0.20% - 29ms]
- 7 个列出的调用加起来为 0.51% / 72ms
- 主要 [99.29% - 14,251 毫秒]
- 线程“.NET SystemEvents”[3,074 毫秒]
- 线程启动 [100% - 3,074 毫秒]
- 运行 [99.6% - 3,072 毫秒]
- ThreadStart_Context [99.93% - 3,072ms]
- 运行 [99.6% - 3,072 毫秒]
- 线程启动 [100% - 3,074 毫秒]
现在,如果我们深入ThreadStart_Context
研究 ,我们会看到以下内容:
- System.Threading.ThreadHelper.ThreadStart_Context(Object) [99.93% - 3,072ms]
- Microsoft.Win32.SystemEvents.WindowThreadProc [99.90% - 3,071ms]
- Microsoft.Win32.UnsafeNativeMethods.MsgWaitForMultipleObjectsEx [87.26% - 2,682ms]
- Microsoft.Win32.SystemEvents.WindowThreadProc [99.90% - 3,071ms]
据分析器称,该MsgWaitForMultipleObjectsEx
API 总共被调用了 26 次。这意味着它每次等待大约等待 100 毫秒。
该Generate
方法是我编写的,它与 ClosedXML 库进行了很多对话。部分操作涉及写入磁盘,但在控制台输出应该出现之后,最后完成了。延迟发生在任何工作完成之前。
我的担忧有两个:
Generate
为什么在主线程调用下结果会有8396ms的时间差异?- 为什么有这么多的调用
MsgWaitForMultipleObjectsEx
,总共需要 3 秒?我知道这可能是由于线程同步造成的,但应用程序中只有 1 个线程。
更新:好的,所以我发现第二个线程实际上是在处理消息循环,所以在那里花费的 5 秒只是没有任何窗口消息要处理的区域。不过,仍然不确定 8 秒的差异来自哪里。