在多线程应用中将会涉及不同的线程访问同一控件的问题,C#中禁止跨线程直接访问控件。某个控件在被创建时就记下了是谁创建了它,即它的创建线程。如果从另一个线程调用该控件,那么必须使用控件的 Invoke 方法来将调用封送现在调用它的线程。
到底是哪个线程要使用该控件呢?需要用InvokeRequired来询问一下,如果当前调用线程不是控件的创建线程,则为 true;否则为 false。
一个典型的使用方法是:
private void ReceiveMessage()
{ IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any,0); while (true) { try { // 关闭receiveUdpClient时此时会产生异常 byte[] receiveBytes = receiveUdpClient.Receive(ref remoteIpEndPoint); string receivemessage = Encoding.Unicode.GetString(receiveBytes); //显示消息内容 ShowMessage(lstMessageBox,string.Format("{0}[{1}]",remoteIpEndPoint,receivemessage)); } catch { break; } } } /// <summary> /// // 通过委托回调机制显示消息内容 /// </summary> delegate void ShowMessageCallback(ListBox listbox,string text); private void ShowMessage(ListBox listbox, string text) {//如果控件的 Handle 是在与调用线程不同的线程上创建的(此时,您必须通过 Invoke 方法对控件进行调用),则为 true;否则为 false。 //如果从另一个线程调用控件的方法,那么必须使用控件的一个 Invoke 方法来将调用封送到适当的线程。 if (listbox.InvokeRequired) { ShowMessageCallback showmessagecallback = ShowMessage; listbox.Invoke(showmessagecallback, new object[] { listbox, text }); } else { listbox.Items.Add(text); listbox.SelectedIndex = listbox.Items.Count - 1; listbox.ClearSelected(); } }