2
我有一个函数,它将控件添加到父控件,该控件从与创建控件的线程不同的线程调用。这是怎么一回事呢:即使在UI线程上执行时的跨线程操作
1 delegate void AddControlToParentDelegate(Control child, Control parent);
2 private void addControlToParent(Control child, Control parent) {
3 if (parent.InvokeRequired) {
4 AddControlToParentDelegate d = new AddControlToParentDelegate(addControlToParent);
5 this.Invoke(d, new object[] { child, parent });
6 } else {
7 parent.Controls.Add(child);
8 }
9 }
10 }
这工作得很好,直到两parent.InvokeRequired
以及child.InvokeRequired
是真实的。然后,一旦执行第5行(现在代理d
被调用并且该函数应该在UI线程上运行(对吗?))child
在第7行会引发一个跨线程操作无效异常。为什么是这样?它不是已经在它创建的线程上运行了吗?
我设法通过增加一个额外(child.InvokeRequired)
检查,以解决这个问题:
delegate void AddControlToParentDelegate(Control child, Control parent);
private void addControlToParent(Control child, Control parent) {
if (parent.InvokeRequired) {
AddControlToParentDelegate d = new AddControlToParentDelegate(addControlToParent);
this.Invoke(d, new object[] { child, parent });
} else {
if (child.InvokeRequired) {
this.Invoke(new MethodInvoker(delegate() {
parent.Controls.Add(child);
}));
} else {
parent.Controls.Add(child);
}
}
}
但这似乎只是可怕的黑客-Y和不必要的。这是做到这一点的方式吗?还是我完全错过了巴士?
此外,设计,*不*使用'InvokeRequired'是更易于维护。我建议为ui线程或使用“BackgroundWorker.ReportProgress”安排一个'Task',它们都是独立于平台的解决方案(即不绑定到Windows窗体)。 – 2010-07-23 01:42:21