c# - 如何知道何时创建了 Windows 窗体上的所有控件句柄?
问题描述
启动时,我的 Windows 窗体中有竞争条件。我想我已经确定了问题,但不确定解决问题的最佳/最简单方法。
- Form 有一个工作线程,它在网络上侦听来自其他服务的消息。该工作线程在“启动”时激活并打开一个套接字以开始侦听。根据接收到的消息内容,可以对表单上的控件进行操作(例如,启用按钮)
- 有时,我会在启动时收到一个 InvalidOperationException,它可以追溯到这个工作线程:
Invoke
或者BeginInvoke
在创建控件之前不能在窗口句柄上调用。
我已经解决了试图操作在主线程上创建的 Windows 控件(通过使用.InvokeRequired
and .Invoke
)的工作线程带来的 CrossThreadException 问题。我已经得出结论,在启动时这里存在竞争条件,该工作线程启动并开始接收来自其他服务的消息,有时在创建表单上所有控件的句柄之前,它会尝试操作一个(启用按钮, 例如)。如果尚未创建该按钮句柄,则会出现异常。
我尝试或考虑尝试的事情:
- 在其他 SO 问题中,我从 MSDN被定向到此页面。我曾希望在
Form.Shown
事件处理程序中启动我的工作线程可以解决问题。但是,中断此事件处理程序并检查环境表明.IsHandleCreated
相关按钮是false
,因此问题仍然存在。 - 在工作线程中打开网络套接字之前,我可以旋转等待,遍历表单中的所有控件并检查它们的
.IsHandleCreated
属性,但看到唯一返回的东西Form.Controls
是表单的直接子级,所以我需要某种递归来检查一切。 - 我可以为所有检查 的函数添加一个额外
.IsHandleCreated
的检查.IsInvokeRequired
,但是其中有很多,并且希望有更简单的东西。 - 与 1 类似,我可以创建一个可以由网络消息操作的所有 Controls 的列表,并让工作线程自旋等待,直到创建了所有 Handles,然后再在网络上侦听。同样,这看起来很笨重且维护成本很高。
所以我的问题是,是否有一种简单/简单的方法可以知道表单上的所有控件何时创建了它们的句柄,之后我将创建这个工作线程来开始监听网络流量?也许是一个事件?或者这是一个 XY 问题,我应该考虑一种完全不同的方法? 这个问题是相关的,但接受的答案(上面的1)并不能解决我的问题。
基本设置是这样的:
// Program.cs
static void Main()
{
....
MyForm form = new MyForm();
Application.Run(form);
}
// MyForm.cs
public MyForm()
{
InitializeComponent();
...
UDP_ReceiveInterface recvInterface = new UDP_ReceiveInterface(...);
}
private void MyForm_Shown(object sender, EventArgs e)
{
recvInterface.Activate();
}
// UDP_ReceiveInterface.cs
...
public void Activate()
{
listenThread_ = new Thread(new ThreadStart(ListenForPackets));
}
private void ListenForPackets()
{
// opens up a socket with network info from a config file
}
我已经尝试将UDP_ReceiveInterface.Activate()
函数移动到不同的地方......在 MyForm 构造函数中,在 Program.csform
中创建之后,如上所示,在MyForm_Shown
事件处理程序中。整个 GUI 由 TabControl 控制,因此所有控件都位于六个 TabPage 之一上。
解决方案
推荐阅读
- python - 如何在python中找到所有有限制的子集?
- python - 如何从 OSMNX 导出 shpfile 中的大量路由
- gcc - 用于不在二进制中生成不需要的符号的编译指示
- python - Python:无法在函数中调用记忆化
- python - Dash rangeslider 'Input' 不是 iterbale
- javascript - 如何使用 websockets、js 和树莓派打开灯
- django - Django migrate - django.db.utils.OperationalError:尝试写入只读数据库
- jquery - 如何使用快速把手、物化、jQuery 和 ajax 基于第一个选项动态填充第二个选择列表?
- python - 分配之前引用的局部变量“final_result”我正在制作一个 django 计算器网络应用程序,但我遇到了这个错误
- python - 将短语列表写入 csv 文件