伙计我知道这个问题已被多次询问,但我仍然找不到对我有用的单一回复。
我的表格上有超过400个控件。
我有一个后台线程,可以轮询一堆设备并收集要在表单上显示的各种数据。
然后我调用一个方法" UpdateDisplay(string [] data)"。这个例程获取字符串数组data []中的所有信息,并填写表单上的所有组件。我填写了标签,文本框。显示和隐藏了面板和TableLayouts以及其他控件。
他们的数百倍!!
如果我必须测试每个组件以查看我是否必须调用我的程序将变成50亿行代码!!!!!
有没有办法简单地看看是否需要在UI线程上调用整个UpdateDisplay方法,而不是它接触到的所有400多个组件?
我输入以下代码:
if (InvokeRequired)
{
BeginInvoke(new MethodInvoker(() => UpdateDisplay(data)));
}
作为display方法中的第一个语句,我不再获得有关从非ui线程调用ui组件的运行时异常。
接下来是更新方法的其余部分,其中数百个组件正在使用data []
中的信息进行更新但是现在我在System.Forms.dll中收到了一堆System.InvalidOperationException ???
如果我将调试异常选项设置为中断所有invalidoperationexceptions,我会看到在使用关于从非ui线程更新组件的讨厌的内容更新UpdateDisplay方法中的组件时,它们会被随机抛出。
有人可以帮我理解并解决这个问题吗?
我可以发布整个UpdateDisplay方法,以显示如果我必须使用invokerequired if语句包装每个组件更新调用,那将是多么荒谬。不夸张它会增加每个控件三行代码或大约1200行额外代码!那太疯狂了!
答案 0 :(得分:2)
这是我如何使用来自另一个线程的消息更新ListBox的示例。
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;
}
}
答案 1 :(得分:2)
您没有提供足够的代码,但如果您的方法看起来像这样:
void UpdateDisplay(string[] data)
{
if (InvokeRequired)
{
BeginInvoke(new MethodInvoker(() => UpdateDisplay(data)));
}
Label1.Text = data[0];
// Update more controls here
}
然后您运行UpdateDisplay
两次,一次在UI线程上由于BeginInvoke
而在BeginInvoke
返回时在工作线程上运行一次。通常的模式是,如果您使用Invoke
或BeginInvoke
来自行调用,则该方法会立即返回并且不会进一步处理:
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
:
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 :(得分:0)
一种可能性是,由于您使用BeingInvoke
,rather than Invoke
来更新UI线程,因此可能存在同步问题。在没有看到更完整的代码示例的情况下很难分辨,请尝试拨打Invoke
并查看是否获得更少的错误