我有一个带有很多控件的大型Windows窗体程序。我运行它时看到的第一个窗口是登录屏幕,它只有一个组合框,按钮,文本框和一些标签。当我按下按钮时,它加载Form1。 Form1,在加载时自动创建一个Game实例,它使用此代码最小化并将Game嵌入到Form1中:
Game.Location = new Point(146, 6);
Game.TopLevel = false;
Game.Visible = true;
Game.BringToFront();
Game.FormBorderStyle = FormBorderStyle.None;
Controls.Add(Game);
我得到了
"创建窗口句柄"
时出错
此行出错(由于某种原因,它不在窗口创建行上):
this.timer.Interval = 10;
请帮助,其他人说这是与太多的窗口有关,但我尝试删除项目中的窗口,我得到同样的错误。
答案 0 :(得分:0)
这个问题似乎已经得到了回答: Error creating window handle
您收到错误是因为您的程序创建的太多了 处理。您的应用程序的窗口句柄限制为10,000 处理。你需要找到内存泄漏。
确保在关闭表单并完成后在表单上调用Dispose(),或使用子句声明表单内部:
using(Form mainForm = new Form())
{
mainForm.Show();
}
Process Explorer或Windows任务管理器允许您查看GDI对象,句柄,线程和USER对象。您将需要执行详细信息选项卡并选择要查看的列(右键单击列 - >选择列)。寻找大量的GDI对象来确认windows句柄限制确实是问题。
您是否正在处理登录表单?你提到你有很多控件,你可以用任何方式限制它们,例如使用标签和文本数组来显示某些东西而不是一堆标签或文本框网格等。
您可以使用的内存分析器示例是.Net Memory Profiler。
(2016年3月30日更新)
修改您提供给我的信息,我发现了三件事:
取消注册活动
如果您要在表单上动态创建然后删除控件,则必须确保从先前使用此控件注册的每个事件中取消注册任何事件处理程序。如果您不这样做,事件处理程序将保留对控件的引用,并且即使您调用Dispose,也不会有资格进行垃圾回收(以及GDI / USER对象)。在您处理父表格之前,它们将一直保留。
计时器(和其他非UI)事件
Timer的tick事件处理程序方法(及其任何调用)中的代码将在不是UI线程的单独线程上运行。如果您需要访问任何UI属性,成员或方法,则必须将线程上下文切换回UI线程,否则这会引发各种各样的时髦异常。此外,如果您从非UI线程创建UI对象(控件),它会创建更多GUI / USER句柄,否则它们可能没有。您可以通过调用Form或Control的Invoke方法来执行此操作,并在匿名方法中执行UI操作或将其委托传递给UI操作代码。如果您也直接从任何UI对象调用该方法,您可能需要检查Control.InvokeRequired以避免使用锁的昂贵的Invoke方法。
<强> AppDomain.FirstChanceException 强>
如果所有其他方法都失败了,你仍然不知道为什么你会得到异常,这是一个聪明的小技巧,我已经习惯了找到非常模糊或难以发现的错误:注册一个事件处理程序AppDomain.FirstChanceException事件,并在处理程序的方法体中放置一个断点。这样,下次抛出异常时,您的代码将获得第一次机会&#39;处理它,你将在我刚才提到的FirstChanceException处理程序方法中点击该断点。从这里,您可以打开调用堆栈窗口,并查看抛出异常的堆栈跟踪。这包括源自本机或.net API的异常。通常情况下,这些信息对您来说是隐藏的,因为在将异常移交给您的代码之前,调用堆栈会被清除。
答案 1 :(得分:0)
只想分享一下我在桌面应用程序启动时就遇到了这个错误,直接是在启动时加载第一个Form时。原来有人在启动可执行文件上配置了兼容模式“ Windows 95”。这似乎导致完全相同的“错误创建窗口句柄”。即使在部署新的.exe之后,仍会在.exe上设置兼容性。我只是希望分享这些内容可以防止其他人浪费我的时间。