昨天我遇到了一个非常奇怪的错误,一天过去了,我几乎没有取得任何进展,所以我认为这是向社区寻求帮助的好机会。我想要请求一些耐心,因为我认为这是一个比较棘手的问题。
我有一个C# Winforms应用程序,在生产环境中点击几次后就会挂起。在开发环境中从未出现过这种情况,只有在生产环境中出现。当挂起发生时,没有什么真正的反应(没有错误消息,但任务管理器显示任务处于“无响应”状态),但GUI变得不响应。我在同样的环境下尝试了它,可以确认这种行为。
不幸的是,在生产环境中无法安装开发工具并调试应用程序。我能做的最好的事情就是在应用程序停止时制作内存转储。问题是我完全不理解在崩溃转储中看到的内容:我的主线程(GUI线程)似乎卡在一个我找不到任何原因的指令上。
以下是我的主线程的堆栈跟踪:
注意:主线程确实停在转储捕获的状态中:每次我进行转储时,结果都是相同的。
注意2:hang从未发生在此代码路径的第一次执行上,在每种情况下,此完全相同的代码路径都在hang之前执行(从应用程序日志推断出)。
如有需要,我可以提供更多细节。 提前感谢您。
编辑: CFAPControlLibrary.dll是应用程序的主要程序集。它包含Windows窗体及其相应的逻辑。使用WCF与服务器通信。较大的请求在后台线程中使用BackgroundWorker进行。您在调用堆栈中看到的执行路径是由此类BackgroundWorker的完成事件调用的。
我在此处粘贴了所请求的代码片段here。
我有一个C# Winforms应用程序,在生产环境中点击几次后就会挂起。在开发环境中从未出现过这种情况,只有在生产环境中出现。当挂起发生时,没有什么真正的反应(没有错误消息,但任务管理器显示任务处于“无响应”状态),但GUI变得不响应。我在同样的环境下尝试了它,可以确认这种行为。
不幸的是,在生产环境中无法安装开发工具并调试应用程序。我能做的最好的事情就是在应用程序停止时制作内存转储。问题是我完全不理解在崩溃转储中看到的内容:我的主线程(GUI线程)似乎卡在一个我找不到任何原因的指令上。
以下是我的主线程的堆栈跟踪:
KERNELBASE.dll!_RaiseException@16() + 0x54 bytes
[External Code]
CFAPControlLibrary.dll!CFAPControlLibrary.Communication.Base.GetSetting(string settingName) Line 850 + 0x10 bytes C#
CFAPControlLibrary.dll!CFAPControlLibrary.ConfigHelper.Get<CFAPControlLibrary.DataTypes.ActionSortingOption>(string settingName) Line 25 + 0x35 bytes C#
CFAPControlLibrary.dll!CFAPControlLibrary.ConfigHelper.Get<CFAPControlLibrary.DataTypes.ActionSortingOption>(string settingName, CFAPControlLibrary.DataTypes.ActionSortingOption defaultVal) Line 15 + 0x9 bytes C# CFAPControlLibrary.dll!CFAPControlLibrary.DataTypes.ActionStorage.Sort(System.Collections.Generic.List<CFAPControlLibrary.DataTypes.ActionClass> subject) Line 167 + 0xe bytes C#
CFAPControlLibrary.dll!CFAPControlLibrary.DataTypes.ActionStorage.GetByStatus(string pStatus) Line 162 + 0x46 bytes C#
CFAPControlLibrary.dll!CFAPControlLibrary.ActionSelector.FillNodes() Line 48 + 0x26 bytes C#
CFAPControlLibrary.dll!CFAPControlLibrary.CFAPMain.OnActionDetailsArrived(CFAPControlLibrary.CFAPMain.RawActionDetails bwr) Line 371 + 0x10 bytes C#
CFAPControlLibrary.dll!CFAPControlLibrary.CFAPMain.OnGetDetailsCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) Line 337 + 0xb bytes C#
user32.dll!_InternalCallWinProc@20() + 0x23 bytes
user32.dll!_UserCallWinProcCheckWow@32() + 0xb3 bytes
user32.dll!_DispatchMessageWorker@8() + 0xe6 bytes
user32.dll!_DispatchMessageW@4() + 0xf bytes
[External Code]
CFAPHost.exe!CFAPHost.Program.Main(string[] args) Line 50 + 0x1d bytes C#
[External Code]
mscoreei.dll!__CorExeMain@0() + 0x38 bytes
mscoree.dll!_ShellShim__CorExeMain@0() + 0x227 bytes
mscoree.dll!__CorExeMain_Exported@0() + 0x8 bytes
kernel32.dll!@BaseThreadInitThunk@12() + 0x12 bytes
ntdll.dll!___RtlUserThreadStart@8() + 0x27 bytes
ntdll.dll!__RtlUserThreadStart@8() + 0x1b bytes
以下是来自顶部堆栈帧的源代码:
KernelBase.dll 的反汇编:
然后是我的代码中的最后一个帧,m_SettingCache 是一个字典,它不包含所请求的键:
注意:主线程确实停在转储捕获的状态中:每次我进行转储时,结果都是相同的。
注意2:hang从未发生在此代码路径的第一次执行上,在每种情况下,此完全相同的代码路径都在hang之前执行(从应用程序日志推断出)。
如有需要,我可以提供更多细节。 提前感谢您。
编辑: CFAPControlLibrary.dll是应用程序的主要程序集。它包含Windows窗体及其相应的逻辑。使用WCF与服务器通信。较大的请求在后台线程中使用BackgroundWorker进行。您在调用堆栈中看到的执行路径是由此类BackgroundWorker的完成事件调用的。
我在此处粘贴了所请求的代码片段here。
我的AppDomain.CurrentDomain.UnhandledException处理程序在这里。
我最初认为不重要但后来证明很重要的堆栈部分(敏感字符串文字已从图像中删除):
这表明调用了Application.Run,我不知道为什么在调用堆栈中没有显示。
更新
在花费三天时间找不到问题原因后,我决定尝试一个变通方法。由于内存转储显示应用程序总是在应抛出KeyNotFound异常的那一点挂起。最直接的解决方法是重构代码以避免可能的异常抛出。该版本通过了测试,从未挂起。 这根本不是一个解决方案,但我们不能再花更多时间在这上面了。所以基本上我祈祷并希望我永远不会再看到这个崩溃。
感谢所有的建议。
!CLRStack
来分析其托管调用堆栈。这将为你提供更多关于快照进程(和线程)以及定位根本原因的见解。除非你对WinDbg和SOS非常熟悉,我建议你通过http://support.microsoft.com打开一个支持案例,并与Microsoft支持团队共享转储文件。 - Lex Li