非常模糊的例外

时间:2013-05-18 08:22:15

标签: c# .net xmlreader

我一直在研究一个利用wunderground的自动完成API的项目,并且我一直遇到一个非常随机的错误。代码位于here

我得到的例外是AccessViolationException。在文本框中输入时偶尔会发生这种情况。

异常信息:

using (XmlReader reader = XmlReader.Create(requestURL))
  

异常:抛出:“指定的注册表项不存在。” (System.IO.IOException)   抛出了System.IO.IOException:“指定的注册表项不存在。”   时间:2013-05-18 14:55:59   线程:主线程[5672]   例外:Caught:“指定的注册表项不存在。” (System.IO.IOException)   捕获到System.IO.IOException:“指定的注册表项不存在。”   时间:2013-05-18 14:55:59   线程:主线程[5672]

Application.Run(new Form1());

  

异常:抛出:“尝试读取或写入受保护的内存。这通常表明其他内存已损坏。” (System.AccessViolationException)   抛出System.AccessViolationException:“尝试读取或写入受保护的内存。这通常表示其他内存已损坏。”   时间:2013-05-18 14:55:59   线程:主线程[5672]

     

异常:抛出:“尝试读取或写入受保护的内存。这通常表明其他内存已损坏。” (System.AccessViolationException)   抛出System.AccessViolationException:“尝试读取或写入受保护的内存。这通常表示其他内存已损坏。”   时间:2013-05-18 15:00:01   线程:主线程[4340]

我在3台不同的计算机上尝试过这种情况,过了一段时间......总会发生同样的错误。

1 个答案:

答案 0 :(得分:1)

我可以在Windows 8上重新启动AccessViolation。您必须启用非托管代码调试并启用符号服务器才能查看原因,麻烦制造者是Windows内置的自动完成消息处理程序。通常是一段相当蹩脚的代码,它通过子类化编辑控件来拦截消息来实现。调用堆栈如下所示:

shell32.dll!CAutoComplete::_StartCompletion()  + 0x4e bytes 
shell32.dll!CAutoComplete::_OnChar()  + 0x7a bytes  
shell32.dll!CAutoComplete::_EditWndProc()  - 0x6ae52 bytes  
shell32.dll!CAutoComplete::s_EditWndProc()  + 0x23 bytes    
comctl32.dll!_CallNextSubclassProc@20()  + 0x92 bytes   
comctl32.dll!_MasterSubclassProc@16()  + 0xa5 bytes 
user32.dll!_InternalCallWinProc@20()  + 0x23 bytes  
user32.dll!_UserCallWinProcCheckWow@36()  + 0xbd bytes  
user32.dll!_DispatchMessageWorker@8()  + 0xf8 bytes 
user32.dll!_DispatchMessageW@4()  + 0x10 bytes  
[Managed to Native Transition]  
System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(System.IntPtr dwComponentID, int reason, int pvLoopData) + 0x24d bytes    
// etc.., not interesting

这是错误的,因为TextChanged事件处理程序中的TextBox.AutoCompleteCustomSource属性赋值。更改该属性具有批次副作用,它会强制重新创建编辑控制窗口,以便新的自动完成列表生效。这与子类代码的交互非常糟糕,可能是因为它仍在使用旧的编辑控件,其窗口被销毁或在Winforms有机会重新初始化新控件之前运行。

解决方法是等待设置属性,直到事件处理完成。使用Control.BeginInvoke()方法可以很好地完成。将属性分配更改为如下所示:

    this.BeginInvoke(new Action(() => {
        textboxInput.AutoCompleteCustomSource = autoComplete;
    }));

现在,文本框的窗口被破坏并在以后重新创建,在处理keydown事件时摧毁了窗口。请注意窗口重建的效果是如何容易看到的,文本框闪烁着便宜的汽车旅馆。我非常怀疑你真的想在运输程序中使用它。