我已经使用目标框架 4.7.2 创建了 Windows 窗体应用程序。我正在与设备进行 USB 通信。当我单击“连接设备”按钮时,用户界面上有 4 个按钮,其中 2 个按钮启用(连接和断开连接),2 个按钮禁用(下载数据和下载日志)。我向设备发送命令并接收响应。我验证设备 ID 是否存储在我的应用程序中,如果存储了,那么我启用这 2 个禁用按钮并显示一个绿色信号。当我单击“断开连接”时,我会禁用这 2 个启用按钮并发出红色信号。
当我第一次打开表单时,这工作得很好。当我关闭该表单并再次打开它时,所有控件的 InvokeRequired 都变为 false。
下面是代码片段。
从主页表格打开表格。
MenuSystem menuSystem = new MenuSystem();
menuSystem.Show();
禁用菜单系统表单中的按钮。
if (btnDownloadData.InvokeRequired)
btnDownloadData.Invoke((MethodInvoker)delegate { btnDownloadData.Enabled = true; });
else
btnDownloadData.Enabled = true;
if (btnDownloadLogData.InvokeRequired)
btnDownloadLogData.Invoke((MethodInvoker)delegate { btnDownloadLogData.Enabled = true; });
else
btnDownloadLogData.Enabled = true;
if (lblDeviceConnection.InvokeRequired)
lblDeviceConnection.Invoke((MethodInvoker)delegate { lblDeviceConnection.BackColor = Color.Green; });
else
lblDeviceConnection.BackColor = Color.Green;
我尝试使用计时器和后台工作人员,但在所有情况下我都得到 InvokeRequired 为 false,并且我还编写了其他情况来修改 GUI,但它也没有反映在 UI 上。
非常感谢您的帮助。
您似乎遇到了问题,当您第二次打开表单时,
InvokeRequired
属性总是返回false
。此行为可能与您生成和呈现 MenuSystem
表单的方式有关。
InvokeRequired
属性用于确定当前线程是否可以直接访问控件,或者是否需要使用控件的Invoke
方法将调用传达给控件的线程。如果当前线程与发起控件的线程不同,则应返回 true
,否则返回 false
。
要解决此问题,请确保您正确生成并显示
MenuSystem
表单。生成新表单时,您应该使用 new
关键字来保证表单的新实例:
MenuSystem menuSystem = new MenuSystem();
menuSystem.Show();
此外,请确保第一次打开
MenuSystem
表单时不会重复使用该表单的现有实例,因为这可能会导致不正确的线程行为。
如果问题仍然存在,您可以尝试以下步骤进行故障排除:
确保每次打开时都会生成
MenuSystem
表单的新实例。
验证启用/禁用按钮和更新 UI 的代码是否按您预期执行。您可以添加一些调试输出来检查
if (InvokeRequired)
块内的代码是否执行。
检查是否抛出任何可能影响表单行为的异常或错误。
考虑使用
BackgroundWorker
或 Task
在单独的线程中处理 USB 通信和 UI 更新,同时使用 Invoke
或 BeginInvoke
从工作线程更新 UI 控件。
以下是如何使用
BackgroundWorker
的示例:
private BackgroundWorker usbWorker = new BackgroundWorker();
// In your form constructor or initialization code
public MenuSystem()
{
InitializeComponent();
// Other initialization code
usbWorker.DoWork += UsbWorker_DoWork;
usbWorker.RunWorkerCompleted += UsbWorker_RunWorkerCompleted;
}
private void ConnectToDeviceButton_Click(object sender, EventArgs e)
{
// Initiate the background worker to handle USB communication
usbWorker.RunWorkerAsync();
}
private void UsbWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Perform USB communication and verify device ID
// Update e.Result with the verification result or any other data needed for UI update
}
private void UsbWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Update UI based on the result from the background worker
if ((bool)e.Result)
{
btnDownloadData.Enabled = true;
btnDownloadLogData.Enabled = true;
lblDeviceConnection.BackColor = Color.Green;
}
else
{
// Handle the case when device ID verification fails
}
}