首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >从非ui线程更新控件

从非ui线程更新控件
EN

Stack Overflow用户
提问于 2015-11-11 12:52:49
回答 3查看 919关注 0票数 3

伙计们,我知道这个问题已经问过很多次了,但我仍然找不到一个对我来说有意义的答案。

我有一个有400多个控件的表单。

我有一个后台线程,它轮询一堆设备并收集要显示在表单上的各种数据。

然后,我将一个方法称为"UpdateDisplay(string[] data)“。这个例程接受字符串数组data[]中的所有信息,并填充表单上的所有组件。我有标签,TextBoxes正在填写。面板、TableLayouts和其他控件正在显示和隐藏。

数以百计的人!

如果我必须测试每一个组件,看看我是否必须调用我的程序将变成50亿行代码!

是否有什么方法可以简单地查看整个UpdateDisplay方法是否需要在UI线程上调用,而不是它所涉及的所有400+组件?

我放置了以下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    if (InvokeRequired)
    {
        BeginInvoke(new MethodInvoker(() => UpdateDisplay(data)));
    }

作为显示方法中的第一个语句,我不再获得关于从非ui线程调用ui组件的运行时异常。

接下来是update方法的其余部分,使用data[]中的信息更新数百个组件

但是现在我在System.Forms.dll得到了一堆System.InvalidOperationException?

如果我将调试异常选项设置为对所有无效操作异常进行中断,则在使用有关从非ui线程更新组件的nastygram更新UpdateDisplay方法中的组件时,会看到它们被随机抛出。

有人能帮我理解并解决这个问题吗?

我可以发布整个UpdateDisplay方法,以说明如果我必须用调用的if语句包装每个组件更新调用,那将是多么不明智。如果不夸张的话,它会在每个控件中增加三行代码,或者大约1200行额外代码!!太疯狂了!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-11-11 13:04:02

您没有提供足够的代码,但是如果您的方法如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void UpdateDisplay(string[] data)
{
    if (InvokeRequired)
    {
        BeginInvoke(new MethodInvoker(() => UpdateDisplay(data)));
    }
    Label1.Text = data[0];
    // Update more controls here
}

然后,您将运行两次UpdateDisplay,一次是在UI线程上运行,一次是由于BeginInvoke而运行,一次是在BeginInvoke返回时在工作线程上运行。通常的模式是,如果使用InvokeBeginInvoke调用自己,则该方法将立即返回,不再进行进一步处理:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void UpdateDisplay(string[] data)
{
    if (InvokeRequired)
    {
        BeginInvoke(new MethodInvoker(() => UpdateDisplay(data)));
        return; // Don't run any code below when BeginInvoke returns
    }
    Label1.Text = data[0];
    // Update more controls here
}

JimmyV还提供了一个替代版本,在BeginInvoke之后也不再做进一步的工作。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void UpdateDisplay(string[] data)
{
    if (InvokeRequired)
    {
        BeginInvoke(new MethodInvoker(() => UpdateDisplay(data)));
    }
    else // Don't run any code below when BeginInvoke returns
    {
        Label1.Text = data[0];
        // Update more controls here
    }
}
票数 2
EN

Stack Overflow用户

发布于 2015-11-11 12:59:35

这是我如何用来自另一个线程的消息更新ListBox的示例。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private void WriteProgressMessage(string message)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new Action(() => this.WriteProgressMessage(message)));
    }
    else
    {
        this.ProgressList.Items.Add(message);
        this.ProgressList.SelectedIndex = this.ProgressList.Items.Count - 1;
        this.ProgressList.SelectedIndex = -1;
    }
}
票数 2
EN

Stack Overflow用户

发布于 2015-11-11 13:07:40

一种可能是,由于您正在使用BeingInvokerather than Invoke来更新UI线程,因此可能会出现同步问题。如果没有看到更完整的代码示例,很难判断,请尝试调用Invoke,看看是否获得了较少的错误。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33659617

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文