我有一个C#程序似乎在随机时间卡住了,并且随机一段时间它恢复了自己!当它卡住时,我可以看到内存增长,当它恢复时,内存使用率就会降到正常水平。 CPU使用率一直都很正常,没有文件写入或读取(按设计)。
程序调用外部(第三方)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个标签和另一个表单(可选)。它似乎在大多数时间都很好,但偶尔会卡住。由于显而易见的原因,我无法在此发布所有代码,但只是试图从我最怀疑的地方进行麻烦。
提前感谢任何建议!
答案 0 :(得分:-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线程。