现在我有一个重要的问题想问一下!我写了一个基于Socket类的多线程服务器和客户端的网络通信!!客户端和服务器连接上了,得到客户端的主机名称,IP地址,端口.现在我想把客户端的主机名称,IP地址,端口在服务器中的ListView控件中显示出来!!问题出现了!!在客户端连接上服务器时,连接的子纯种启动,把接收到的客户端的主机名称,IP地址,端口放到我自己定义的DataTable里,在把DataTable里的数据放到ListView控件里时就出现线程间操作无效,从不是创建控件的"ListView"访问它.出现一个System.InvalidOperationException异常~!~~这是什么问题???请高手指教!~~~~这问题是在线程里不能创建控件操作还是我的代码有错呢??
还有一个问题,就是如果用委托去操作这个ListView控件,又应该怎么去做?请高手指教,最好有示例说明!~~~~~

解决方案 »

  1.   

    MSDN解释
    :
    访问 Windows 窗体控件本质上不是线程安全的。如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用情况和死锁。确保以线程安全方式访问控件非常重要。.NET Framework 有助于在以非线程安全方式访问控件时检测到这一问题。在调试器中运行应用程序时,如果创建某控件的线程之外的其他线程试图调用该控件,则调试器会引发一个 InvalidOperationException,并提示消息:“从不是创建控件 control name 的线程访问它。”
    可以通过将 CheckForIllegalCrossThreadCalls 属性的值设置为 false 来禁用此异常。这会使控件以与在 Visual Studio 2003 下相同的方式运行。

    CheckForIllegalCrossThreadCalls =false不是最好的方法.
    最好的方法是用异步.如下:namespace WindowsApplication7
    {
        public partial class Form1 : Form
        {
            private Thread th;
            public Form1()
            {
                InitializeComponent();        }
            private void button1_Click(object sender, EventArgs e)
            {
                th.Start();
            }
            private delegate void ControlDel(string txt);//异步委托
            private void Form1_Load(object sender, EventArgs e)
            {
                th = new Thread(method);
            }
            private void method(object args)
            {
                ControlDel del = delegate(string text)
                {
                    textBox1.Text = text;
                };
                this.Invoke(del, new object[1] { "texttext" });
            }
        }
    }
      

  2.   

    我按你的说法,写了一个异步委托!~~异常已经解决了!~~但是还是显示不了数据,可能我不会写异步委托!~~~我是这样写的!!!
    private delegate void SetDataTableList(DataTable dt);IPAddress clIP = IPAddress.Parse(PortIP[0].ToString());
    string ClientName = Dns.GetHostEntry(clIP).HostName.ToString();
    string ClientIP = PortIP[0].ToString();
    string ClientPort = PortIP[1].ToString();
    userList.Rows.Add(ClientName, ClientIP, ClientPort);
    //调用异步委托
    SetDateTable(userList);Thread thService = new Thread(new ThreadStart(ServiceClient));
    thService.IsBackground = true;
    thService.Start();//异步委托
    private void SetDateTable(DataTable dt)
    {
     if (this.listView1.InvokeRequired)
     {
       SetDataTableList d = new SetDataTableList(SetDateTable);
       this.Invoke(d, new object[] { dt });
      }
    }
      

  3.   

    我已经解决了~~~谢谢hopewoo都了我的方法!~~~~把分全给你啦!!!
      

  4.   

    这实际上是跨线程访问控件的问题,对于WinForm和WPF解决原理类似,方法有些不一样:
    具体的请看这篇文章:WinForm(C#)中跨线程访问控件的解决方法