本帖最后由 ericmpdeng 于 2014-12-18 17:12:19 编辑

解决方案 »

  1.   

    连接已关闭  说明没有open,那个方法出的错?
      

  2.   

    最后一个啊,dataset这个,我原来的代码里每次调用都加了,getcon(),完了都加了con_close();的
      

  3.   

    private void ReceiveMessage()
            {
                IPEndPoint remoteIPendPoint = new IPEndPoint(IPAddress.Any, 6208);
                while (true)
                {
                    try
                    {
                        
                        byte[] receivebytes = receiveUdpClient.Receive(ref remoteIPendPoint);
                        string message1= Encoding.Unicode.GetString(receivebytes, 0, receivebytes.Length).Trim();
                        string[] splitstring = message1.Split(',');
                        int a = message1.Length;
                        switch (splitstring[0])
                        {
                            case "login":
                                IPEndPoint clientipendpoint = new IPEndPoint(IPAddress.Parse(splitstring[2]),  udpport);
                                string user = splitstring[1];
                                lock (userip)
                                {
                                    if (userip.ContainsKey(user))
                                    {
                                        userip[user] = splitstring[2];
                                    }
                                    else
                                    {
                                        userip.Add(user, splitstring[2]);
                                    }
                                }
                                SqlDataReader mydr = mydataclass.getcom("select * from userinfo where name='" + user + "'");
                                if (mydr.HasRows)
                                {                                mydataclass.getsqlcom("update userinfo set ip='" + splitstring[2].ToString() + "',mac='" + splitstring[3] + "',logtime='" + DateTime.Now + "'where name='" + user + "'");
                                    mydataclass.con_close();
                                }
                                else
                                {                                mydataclass.getsqlcom("insert into userinfo (name,ip,mac,logtime) values('" + user + "','" + splitstring[2].ToString() + "','" + splitstring[3] + "','" + DateTime.Now + "')");
                                    mydataclass.con_close();
                                }
                                break;
                            case "talk":
                              
                                string num = splitstring[1];
                                string sname = splitstring[3];
                                string pname = splitstring[4];
                                string t = splitstring[2];
                                string yanz = sname + ',' + "myz:" +","+ splitstring[1];
                                Thread thyanz = new Thread(myztoClient);
                                thyanz.IsBackground = true;
                                thyanz.Start(yanz);
                                string mess1=message1.Substring(splitstring[0].Length + splitstring[1].Length + splitstring[2].Length + splitstring[3].Length + splitstring[4].Length + 5, message1.Length - splitstring[0].Length - splitstring[1].Length - splitstring[2].Length - splitstring[3].Length - splitstring[4].Length-5);
                                mydataclass.getsqlcom("insert into history (name,content1,time,bs,stats) values('" + pname + "','" + mess1 + "','" + Convert.ToDateTime(t) + "','" + sname + "','" + '1' + "')");
                                if (pname == severnam)
                                {
                                }                            break;
                        }
                    }
                              
                    catch
                    {
                        
                    }
                    
                }        }
      private void myztoClient(object obj)
            {
                try
                {
                    string message = (string)obj;
                    string[] message1 = message.Split(',');
                    ysendUdpClient = new UdpClient(0);
                    byte[] sendbytes = Encoding.Unicode.GetBytes(message.Substring(message1[0].Length + 1, message.Length - 1 - message1[0].Length));
                                       DataSet userds1 = mydataclass.getdataset("select * from userinfo where name='" + message1[0].Trim() + "'", "userinfo1");
                        string reip = Convert.ToString(userds1.Tables[0].Rows[0][2]);
                        IPEndPoint remoteipendpoint = new IPEndPoint(IPAddress.Parse(reip), 6210);
                        ysendUdpClient.Send(sendbytes, sendbytes.Length, remoteipendpoint);
                        ysendUdpClient.Close();
                               }
                catch
                {
                    Thread.CurrentThread.Abort();
                }
            }        #endregion这是我其中一个调用!
      

  4.   


    public static SqlConnection my_con;不用要static, 在每个线程里面, new 一个新的SqlConneciton出来, 用新的SqlConnection进行Open和Close操作.如果使用的是static,  线程A和线程B同时访问这个sqlconnection, 线程B先执行完了, 给关闭了. 线程A怎么办?
      

  5.   

    或者你的数据库操作类里的函数,函数自身负责open,close
    而不是有的函数负责open,有的负责close,有的负责查询
    那你多线程同时调用不同的函数,可不是就乱套了吗
      

  6.   

    哪不是要产生很多SQL连接?我没开一个线程就要重启连接,有没有科学一点的办法?
      

  7.   

    只有创建新的 SqlConnection,人家才能使用连接池,从而解决并发使用连接时的分配和重用问题。而你使用 static 的,你根本不去用连接池。你说哪一个写法才科学?给打个比方吧。比如说高铁车卖座票,是一趟一张票的。你说“不,你必须卖给我一个座一年的票,至于怎么用是我自己的事儿你不用管,否则你就是不‘科学’的。”你说你科学吗?
      

  8.   


    你一点也没有搞懂什么叫连接池。在你的程序创建逻辑连接对象之前,可能 ado.net 已经创建了10个物理连接对象。在你的程序创建了100个逻辑对象之后,只要你遵循“用完了应该立刻释放 DbConnection 对象的原则”,那么此时人家可能也不过只是创建了15个物理连接。而且当你创建第101个逻辑连接之后,也还是再用这15个物理连接。这就相当于你创建的是“车票”,而不是什么“车座”。 DbConnection 是逻辑连接,不是物理连接。
      

  9.   

    不用维护数据库的连接池吧,你能open就说明能用,所以每个线程实例化成功后判断下是不是open了就好了,线程结束了就close掉。
      

  10.   

    这种连接的操作本来就不能用多线程(Socket也同理)static : Conn;
          线程A            线程B
    Conn.Open
                             Conn.Open
         ....                    .....
    Conn.Close
                             Conn.Read  => 异常了,连接已被线程A关闭
                             Conn.Close
    楼主的异常就属于上面演示的这种情况。
      

  11.   

    帮你做了一些修改,你看看能用么;自己看做这个程序和你自己写的有哪些不一样,特别是实例化的地方。    public class mydataclass
        {         public string my_sql = "", my_tabale = "", my_field = "", my_data="";
            public SqlConnection my_con;
            public string m_str_sqlcon = "Data Source=127.0.0.1;Database=em;User id=sa;PWD=''";        public mydataclass()
            {
                my_con = getcon();
            }
            public SqlConnection getcon()
            {
                    my_con = new SqlConnection(m_str_sqlcon);
                    my_con.Open();
                    return my_con;
                }        
            public void con_close()
            {
                if (my_con.State == ConnectionState.Open)
                {
                    my_con.Close();
                    my_con.Dispose();
                }
            }
            public SqlDataReader getcom(string sqlstr)
            {            
                SqlCommand my_com = my_con.CreateCommand();
                my_com.CommandText = sqlstr;
                SqlDataReader my_read = my_com.ExecuteReader();
                return my_read;
            }//只读方式打开数据库
            public void getsqlcom(string sqlstr)
            {
                SqlCommand sqlcom = new SqlCommand(sqlstr, my_con);
                sqlcom.ExecuteNonQuery();
                sqlcom.Dispose();
               
            }//对数据库执行添加删除操作        public static void GetSqlCom(string sqlstr)
            {
                var mc = new mydataclass();
                mc.getcom(sqlstr);
                mc.con_close();
            }        public DataSet getdataset(string sqlstr, string tablename)
            {
                
                
                    SqlDataAdapter sqlda = new SqlDataAdapter(sqlstr, my_con);
                    DataSet my_data = new DataSet();
                    my_data.Clear();
                    sqlda.Fill(my_data, tablename);
                    return my_data;
            }
                }
      

  12.   


    楼主我觉得你已经Get到了那个Point。只是怕占用资源太多而已。
    我觉得.NET应该具备保护机制,像ThreadPool可以SetMaxThreads一样。
      

  13.   

    连接池貌似不需要管理的吧,至少我开发这么多年来貌似都没有去管理过连接池。
    不可以数据库连接的时候建立一个连接池,然后启动线程的时候去调用连接池的连接么,我是新手!感谢指教
    连接池是数据库自身自带功能管理的,属于数据库的一部分,不需要编程额外去管理。你这里使用到了多线程,那么你只需要管理你的线程池。
    那比如我启动一个线程,这个线程带SQL连接,哪我这个线程的数据库连接的SqlConnection都要不一样额?
      

  14.   

    既然是多线程,那为什么只用同一个my_con,这显然是不对的,应该各用各的才对.
      

  15.   

    额,那比如我启动一个线程,这个线程带SQL连接,哪我这个线程的数据库连接的SqlConnection都要不一样额?
      

  16.   

    连接池貌似不需要管理的吧,至少我开发这么多年来貌似都没有去管理过连接池。
    不可以数据库连接的时候建立一个连接池,然后启动线程的时候去调用连接池的连接么,我是新手!感谢指教
    连接池是数据库自身自带功能管理的,属于数据库的一部分,不需要编程额外去管理。你这里使用到了多线程,那么你只需要管理你的线程池。
    那比如我启动一个线程,这个线程带SQL连接,哪我这个线程的数据库连接的SqlConnection都要不一样额?
    保证某一瞬间所有并发执行的线程所使用的数据库连接都是独立的,也就是不管你多少人来,我售票窗口不可能一次同时听两个人说话,并同时完成两个人指令,所以必须是不同的。
      

  17.   

    额,那比如我启动一个线程,这个线程带SQL连接,哪我这个线程的数据库连接的SqlConnection都要不一样额?
    如果你只启动一个线程,哪里有一样不一样的区别
    好比你问:我自己去银行,那我每次是否都需要去不同的窗口排队?只有一个人,排哪里不一样
      

  18.   

    private void ReceiveMessage()
            {
                IPEndPoint remoteIPendPoint = new IPEndPoint(IPAddress.Any, 6208);
                while (true)
                {
                    try
                    {
                        
                        byte[] receivebytes = receiveUdpClient.Receive(ref remoteIPendPoint);
                        string message1= Encoding.Unicode.GetString(receivebytes, 0, receivebytes.Length).Trim();
                        string[] splitstring = message1.Split(',');
                        int a = message1.Length;
                        switch (splitstring[0])
                        {
                            case "login":
    .......
    这里,我准备接收一个消息启用一个线程处理消息,每一条消息,我都带有一个随机验证码,收到消息都要返回随机码,告诉发信息的客户,收到信息,所以收到一条消息就会先后启动两个线程,每个线程都有数据库连接,如果我同时收到2条消息,就会有4个线程,要确保这4个线程的SqlConnection都不一样才行额?
      

  19.   

    UDP接收消息是不是只能用一个线程?
      

  20.   

    UDP接收消息是不是一个端口只能用一个线程?
      

  21.   


    SqlConnection 本身有连接池机制。你另外再发明一套连接池,而且还出错了,这怎么办?删掉你自己的连接池代码就行了!
      

  22.   

    再给你重复一遍基本的原则:使用 SqlConnection 逻辑连接对象需要尽快关闭,例如要写在using (var my_con = new SqlConnection(m_str_sqlcon))
    {
        my_con.Open();
        .........//这里进行数据库查询更改
    }  //这里立刻自动关闭了 my_con。只有你尽快关闭 my_con,那么原来的这个底层物理才能高速地共享给别的逻辑连接。这是 SqlConnection 最基本的使用方法!而且这显然也不会在不同线程中去共享什么连接,既不会出现什么“已经打开”错误,也不会出现什么“连接已关闭”错误。如果你觉得你发明的连接池比 SqlConnection 的好,那么想办法卖给微软、或者其它需要的公司。不要在人家 SqlConnection 上面又来一套破坏人家使用方法的东西。
      

  23.   

    原来的这个底层物理才能高速地共享 -->  原来的这个底层物理连接才能高速地共享如果你要自己开发什么连接池,你应该使用没有连接池机制的更底层的类库上去开发。不应该去多余地用 SqlConnection。