在我们的 .Net CF 应用程序中,我们从不应该有问题的部分代码中得到奇怪的错误。例如,下面的代码:
public void AddParm(string str)
{
string[] pair = str.Split('=');
string key = pair[0].Trim();
string value = pair.Length > 1 ? pair[1] : "";
if (key.Length > 0)
{
if (_parmTable.ContainsKey(key))
_parmTable[key] = value;
else
_parmTable.Add(key, value);
}
}
调用 AddParm() 的例程将调用包装在 Try...Catch 块中,捕获所有异常类型。
public void Unpack(string txn)
{
try
{
// split out strings like: "EVENTLABEL:x=1,y=2,z=3"
char chEvent = ':';
char chSeparator = ',';
_parmTable = new Hashtable();
int iEvent = txn.IndexOf(chEvent);
if (iEvent == -1)
_eventLabel = txn;
else
{
_eventLabel = txn.Substring(0, iEvent);
string parms = txn.Substring(iEvent + 1).TrimEnd('\n');
string[] items = parms.Split(chSeparator);
if (items.Length <= 0)
AddParm(parms);
else
foreach (string item in items)
AddParm(item);
}
}
catch (Exception ex)
{
AppLog.logException(string.Format("UnpackedTask.Unpack: Error parsing '{0}'", txn), ex);
}
}
我刚刚得到一个核心未处理异常,将故障模块列为 mscoree3_5.dll。堆栈跟踪显示:
在 ArrayList.InternalSetCapacity(Int32 值,布尔 updateVersion) 在 ArrayList.EnsureCapacity(Int32 分钟) 在 ArrayList.Add(对象值) 在 String.Split(Char[] 分隔符) 在 AddParm(字符串 str)
这发生在工作线程上。
我确实在 Main 中使用 AppDomain.CurrentDomain.UnhandledException 注册了一个处理程序,但它也没有捕获异常。
不幸的是,出现的 WinCE 错误对话框没有说明错误类型或给出错误消息,只是它在 mscoree3_5.dll 和堆栈跟踪中。
我们创建了由 AddParm 解析的值,我认为 AddParm 具有足够的防御性,它可以在 Split 调用之前捕获任何潜在的问题。由于调用 AddParm 的方式,它永远不会用空字符串调用。即使我不相信 AddParm 可以用无效的东西调用,包装调用的 Try...Catch 应该总是捕获异常,但它没有。
同样,我们也看到了像这样的未捕获错误:
BbCore.exe 发生本机异常 在 RuntimeType.InternalGetField(rt…) 在 RuntimeType.InternalGetField(rt…) 在 SRSupport.GetString() 在 SRSupport.GetString() 在 IPAddress.Parse(String ipString)
这是今天早上的完整堆栈跟踪:
在 CurrentSystemTimeZone.GetDaylightChanges(Int32 年) At CurrentSystemTimeZone.GetUtcOffsetFromUniversalTime(DateTime time, Boolean& isAmbiguousLocalDst) 在 CurrentSystemTimeZone.ToLocalTime(DateTime 时间) 在 DateTime.ToLocalTime() 在 DateTime.get_Now() 在 MainLoop.timer1_Tick(Object sender, EventArgs e) 在 Timer._WnProc(WM wm, Int32 wParam, Int32 lParam) 在 ApplicationThreadContext._InternalContextMessages(WM wm, Int32 wParam, Int32 lParam) 在 NativeMethods.GetMessage(MSG& lpMsg,IntPtr hWnd,UInt32 wMsgFilterMin,UInt32 wMsgFilterMax) 在 Application2.Pump() 在 Application2.RunMessageLoop(Boolean showForm) 在 Application2.Run(Form mainForm, Boolean runAsSingletonApp, Boolean displayMainForm) 在 Startup.Main()
Application2 引用是由于使用了 OpenNetCF.Windows.Forms.dll。我从未见过代码的那部分崩溃,它基本上是随机的。
这是从捕获所有异常类型的 Try...Catch 中调用 IPAddress.Parse 的另一种情况。在那种情况下,我相信 Parse 可以使用空字符串调用,但我不明白为什么它显示为未处理的异常,甚至没有被我们的未处理异常处理程序捕获,而是被 WindowsCE 捕获异常处理程序并导致整个应用程序崩溃。
自从我们从 R2 更新到 WinCE 6 R3 平台构建器以来,这些似乎更常见。我不确定它们是否曾经在 R2 下发生过,但它们肯定不那么频繁。即使现在它们并不总是发生 - 我无法可靠地复制它们。
有任何想法吗?为什么框架的核心部分会抛出 Try..Catch 无法捕获的错误?
额外信息: 看来我遗漏了一条关键信息。ExceptionCode 列为 0x80000002,这似乎是本机内存不足异常。根据垃圾收集器的说法,我们的应用程序很少使用超过 1MB 的内存。根据 coredll.dll 的 GlobalMemoryStatus,系统的典型内存负载约为 29%(57MB 中有 41MB 空闲)。是否有任何好的实用程序可以监控和记录一段时间内的总系统内存使用情况?我开始怀疑我用来测量内存使用的技术是否没有我想象的那么准确。使用 OpenNetCF.ToolHelp.ProcessEntry.GetProcesses() 显示我们的进程使用了大约 3.6MB,NK.exe 使用了大约 2.5MB。