第二次打开表单时InvokeRequired为假

问题描述 投票:0回答:1

我已经使用目标框架 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 上。

非常感谢您的帮助。

c# .net winforms desktop-application
1个回答
0
投票

您似乎遇到了问题,当您第二次打开表单时,

InvokeRequired
属性总是返回
false
。此行为可能与您生成和呈现
MenuSystem
表单的方式有关。

InvokeRequired
属性用于确定当前线程是否可以直接访问控件,或者是否需要使用控件的
Invoke
方法将调用传达给控件的线程。如果当前线程与发起控件的线程不同,则应返回
true
,否则返回
false

要解决此问题,请确保您正确生成并显示

MenuSystem
表单。生成新表单时,您应该使用
new
关键字来保证表单的新实例:

MenuSystem menuSystem = new MenuSystem();
menuSystem.Show();

此外,请确保第一次打开

MenuSystem
表单时不会重复使用该表单的现有实例,因为这可能会导致不正确的线程行为。

如果问题仍然存在,您可以尝试以下步骤进行故障排除:

  1. 确保每次打开时都会生成

    MenuSystem
    表单的新实例。

  2. 验证启用/禁用按钮和更新 UI 的代码是否按您预期执行。您可以添加一些调试输出来检查

    if (InvokeRequired)
    块内的代码是否执行。

  3. 检查是否抛出任何可能影响表单行为的异常或错误。

  4. 考虑使用

    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
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.