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