在C#多线程编程或者使用委托异步编程的时候,经常会遇到这样的错误:
从不是创建某个控件的线程的其他线程调用该控件。例如:
private void setTextUnsafeBtn_Click(
object sender,
EventArgs e)
{
this.demoThread =
new Thread(new ThreadStart(this.ThreadProcUnsafe));
this.demoThread.Start();
}
// This method is executed on the worker thread and makes
// an unsafe call on the TextBox control.
private void ThreadProcUnsafe()
{
this.textBox1.Text = "This text was set unsafely.";
}
有的人可能找到的方法是加这一句CheckForIllegalCrossThreadCalls = false,设置为不检查调用控件的合理性,但这样是不安全的。
正确的解决方法是
-
查询控件的 InvokeRequired 属性。
-
如果 InvokeRequired 返回 true,则使用实际调用控件的委托来调用 Invoke。
-
如果 InvokeRequired 返回 false,则直接调用控件。
private void setTextSafeBtn_Click( object sender, EventArgs e) { this.demoThread = new Thread(new ThreadStart(this.ThreadProcSafe)); this.demoThread.Start(); } // This method is executed on the worker thread and makes // a thread-safe call on the TextBox control. private void ThreadProcSafe() { this.SetText("This text was set safely."); }
其中SetText函数为:private void SetText(string text) { // InvokeRequired required compares the thread ID of the // calling thread to the thread ID of the creating thread. // If these threads are different, it returns true. if (this.textBox1.InvokeRequired) { SetTextCallback d = new SetTextCallback(SetText); this.Invoke(d, new object[] { text }); } else { this.textBox1.Text = text; } }