背景
我们有一个用C#编写的.NET WinForms应用程序,它通过控制台应用程序连接到手持式商店扫描仪。控制台应用程序是用很好的'VB6编写的 - 那里没有托管代码。 VB6应用程序由几个COM对象组成。
.NET WinForms应用程序通过使用正确的参数调用控制台应用程序来刷新扫描程序中的数据。当控制台应用程序启动时,它会弹出一个模态表单,提醒用户将手持设备放入其底座。
问题
客户有一种奇怪的情况,即启动控制台应用程序的调用在显示提醒表单之前似乎已挂起。如果用户按下任何键 - 即使是像Shift或Alt这样无辜的东西 - 应用程序也会解冻,并显示提醒表单。当它挂起时,控制台应用程序的CPU使用率非常高。
我们使用ProcDump从命令行应用程序获取了内存转储。我有一些调试托管转储文件的经验,但这个VB 6转储对我来说很奇怪。
我们连续捕获了几个完整的内存转储。在其中一些中,似乎有COM胶水堆。例如,几个转储文件显示如下调用堆栈:
msvbm60!BASIC_DISPINTERFACE_GetTICount
msvbm60!_vbaStrToAnsi
msvbm60!IIDIVbaHost
msvbm60!rtcDoEvents
msvbm60!IIDIVbaHost
msvbm60!BASICCLASS_QueryInterface
[our code which I think is trying to create and invoke a COM object]
我所拥有的唯一符号来自我们的代码并没有帮助。 Microsoft符号服务器没有msvbm60.dll的PDB文件(或者至少不是其版本6.0.98.2)。
问题
我怀疑可能有一些COM线程问题只发生在他们的系统上。
1)如何确定转储文件中每个线程的线程状态?如果这是一个托管转储文件,我会查看!threads
,然后查看!threadstate
以找出线程状态。没有托管代码,所以我不能使用sos.dll。我没有看到使用~
和!teb
的任何提示。
2)有没有办法查看转储文件中创建了哪些COM对象?同样,在托管转储中,我可以执行!dumpheap
来获取托管对象列表。我能为COM对象找到类似的东西吗?
3)我可以在转储文件中确定COM对象的线程模型吗?
答案 0 :(得分:2)
您可以使用命令转储线程状态:
~*
这不会将'background'显示为状态,您只会看到正在运行,冻结或暂停。
我不确定如何从COM对象获取信息,我从未尝试过,但我会调查并回复您,对于线程模型的问题,很难推断出在没有痛苦地监视应用程序状态之后即使这样,当你逐步浏览所有其他线程时,除非你使用.bpsync 1
同步所有线程到当前线程,但这可能会导致挂起(例如gui线程现在被告知冻结)所以我认为除非你有权访问源代码,否则很难。
答案 1 :(得分:1)
我只能回答问题1.使用!runaway
查找消耗CPU的线程。要获取所有线程堆栈,请使用~*kb1000
。