如何在 C# 中调用多个控件
Posted
技术标签:
【中文标题】如何在 C# 中调用多个控件【英文标题】:How to Invoke multiple controls in C# 【发布时间】:2017-09-05 21:03:54 【问题描述】:我有一个 C# 程序似乎在随机时间卡住了,在随机一段时间后它自行恢复了!当它卡住时,我可以看到内存增长,当它恢复时,内存使用量就下降到正常水平。 CPU 使用率一直正常,没有文件被写入或读取(按设计)。
程序调用外部(第 3 方)DLL 函数与硬件通信,并从运行在不同线程上的 DLL 回调更新 UI。我检查了代码,除了以下代码(已编辑)之外没有发现任何可疑之处:
private void Func(StructType para)
if (labelA.InvokeRequired)
labelA.BeginInvoke(new MethodInvoker(() => Func(para)));
return;
if (labelB.InvokeRequired)
labelB.BeginInvoke(new MethodInvoker(() => Func(para)));
return;
labelA.Text = para.A;
labelB.Text = para.B;
我想知道这是否是从另一个线程更新 UI 元素的正确方法?如果没有,如何修改?
事实上,我调用了 6 个标签和另一种形式(可选)。大多数时候它似乎工作正常,但偶尔会卡住。由于显而易见的原因,我无法在此处发布所有代码,而只是试图从我最怀疑的地方进行故障排除。
提前感谢您的任何建议!
【问题讨论】:
可能是死锁,UI 线程正在执行其他操作(使用 Debug > Windows > Threads 进行诊断)。或者你调用 BeginInvoke() 过于频繁,所以 UI 线程除了处理调用之外不能做任何其他事情,每秒 50 次对于人眼来说已经足够了。 @HansPassant 是的,还有其他函数调用 Invoke 到其他控件。第 3 方 SDK 的示例代码编写相同,但每个函数只有一个 Invoke。我修改了代码,发现我需要同时更新多个标签,这就是我放置多个调用的原因。您能建议一些正确的方法吗? 另一个问题是,如果它导致死锁,为什么它会在某个时候无缘无故地恢复自己?我的应用程序中的回调应该是一个函数每秒调用 30 次,每秒调用另外 30 次,每秒调用一次不同的调用。第一个更新 6 个标签和另一个全屏表单(用于在屏幕上显示图像),第二个更新一个图片框,最后一个更新一个富文本框。当它卡住时,它会等待不同的时间并开始“刷新缓冲区”,并且在刷新缓冲区之前的不同时间会再次卡住,然后循环:( 【参考方案1】:您不需要单独检查每个控件以确定是否需要调用它 - 只有一个 UI 线程,因此,该检查仅有用一次。请记住——修改任何 UI 组件几乎肯定会级联成一大堆对其他 UI 组件的其他读/写操作;因此,您必须假设如果您正在触摸 任何 UI 对象,则必须假设您正在触摸 所有 UI 组件。
考虑到这一点,我建议您执行一次调用检查,并建议对两个标签的父控件执行检查和调用。
假设 this
指的是这两个标签的父类,我将修改您的代码如下:
private void Func(StructType para)
if (this.InvokeRequired)
// Elide the explicit delegate declaration; it's not necessary.
this.BeginInvoke( Func(para) );
// Elide the return statement - multiple returns are messy, and in this case, easily removed.
else
labelA.Text = para.A;
labelB.Text = para.B;
请注意,如果对象被释放,InvokeRequired
返回 false,即使调用线程不是 UI 线程。
【讨论】:
谢谢。它肯定不会被处理掉。我没有尝试在父级(即表单)上调用,但是如果多个回调函数尝试同时调用表单会导致问题吗?另外,谁能解释为什么投反对票?谢谢!以上是关于如何在 C# 中调用多个控件的主要内容,如果未能解决你的问题,请参考以下文章