none
关于公共函数多用户同时访问的问题。 RRS feed

  • 问题

  • 情况是这样的,我在一个类中建立了一个公共函数。
            public void AutoAssign(Admin admin, EnumerableRowCollection<DataRow> datarow)
            {
               List<DataRow> dr = datarow.ToList<DataRow>();
    
                lock (dr)
                {
                    //系统自动配题
                    if (IsAssign())
                    {
                        //在配题时间内
    
                        for (int i = 0; i < dr.Count; i++)
                        {
                            //循环当前列表中的在线教师
                            //string Subject = dr[i]["UserSubject"].ToString();
                            //int Count = Convert.ToInt32(dr[i]["Count"]);
                            if (int.Parse(dr[i]["Count"].ToString()) < int.Parse(Connect.Get("MaxForum")))
                            {
                                //获得状态为提问,并且为主题的帖子按照发布时间升序
                                string SqlString = "SELECT TOP 1 * FROM Sys_Forum_tbl Where State = " + (int)Connect.State.提问 + " AND IsMaster = 'True' AND Subject = '" + dr[i]["UserSubject"].ToString() + "' Order By PostTime ASC";
                                SqlDataReader reader = (SqlDataReader)Connections.GetDataReader(SqlString, Connections.Connect(Connect.Get("Conn")));
                                if (reader.Read())
                                {
                                    //题目处理步骤
                                }
                                reader.Close();
                            }
                        }
                    }
                }
            }

    调用的时候是以页面间隔刷新为方法,每隔N秒执行一次,在多用户同时登陆后访问的频率很高。访问方法为

            DataTable dt = Application["OnlineTable"] as DataTable;

            var query = from i in dt.AsEnumerable()
                        where int.Parse(i["UserLevel"].ToString()) == (int)Connect.AdminLevel.答疑教师
                        orderby i["Count"] ascending
                        select i;//查询在线列表中用户权限为答疑教师的记录

            Automata auto = new Automata();
            auto.AutoAssign(Session["AdminInfo"] as Admin, query);

    单用户的时候不会发生问题,多用户尤其是各种学科同时出现在Application中的DATATABLE中后,会出现并未按照预定的结果来处理的情况,也就是说语文在线教师会得到一些本不该得到的数据记录。请问这个该如何改进?

    2009年9月19日 17:21

答案

  • 你好!
         你使用的lock (dr)不能起到同步的作用,因为dr是局部变量,每次调用这个方法都会重新建立这个局部变量的!既然每次dr都是不同的变量,那也就起不到同步的作用了!
          根据你的需求,有二种同步策略可以选择:
          1,把dr定义成类的字段,使用lock(dr)可以同步类的同一个实例同时调用这个方法的情况。
          2,可以使用另外定义一个静态字段,专门用来同步,使用lock(staticField)可以同步类的不同实例同时调用这个方法的情况。
          第二中策略更加的严格,但是开销也更大,主要看你的需求是怎样的,如果必须要同步类的不同实例同时调用这个方法的情况,那就必须使用第二种策略了
          希望这些建议对你有帮助!
    周雪峰
    2009年9月20日 6:38
    版主

全部回复

  • 是不是哪里逻辑问题?调试看看?使用单例模式试试?
    2009年9月20日 2:20
  • 你好,多用户的时候你需要把在线教师带入到查询条件中,比如你的 select  及 query
    知识改变命运,奋斗成就人生!
    2009年9月20日 2:57
    版主
  • 你好,多用户的时候你需要把在线教师带入到查询条件中,比如你的 select  及 query
    知识改变命运,奋斗成就人生!

    他那不是用Where筛选了吗?
    2009年9月20日 3:02
  • 如果单用户没问题,那么基本上对共享资源的操作问题,您是不是也有写操作啊,
    建议把lock改为lock(this)。
    或者把完整代码贴出
    2009年9月20日 3:36
  • 你好!
         你使用的lock (dr)不能起到同步的作用,因为dr是局部变量,每次调用这个方法都会重新建立这个局部变量的!既然每次dr都是不同的变量,那也就起不到同步的作用了!
          根据你的需求,有二种同步策略可以选择:
          1,把dr定义成类的字段,使用lock(dr)可以同步类的同一个实例同时调用这个方法的情况。
          2,可以使用另外定义一个静态字段,专门用来同步,使用lock(staticField)可以同步类的不同实例同时调用这个方法的情况。
          第二中策略更加的严格,但是开销也更大,主要看你的需求是怎样的,如果必须要同步类的不同实例同时调用这个方法的情况,那就必须使用第二种策略了
          希望这些建议对你有帮助!
    周雪峰
    2009年9月20日 6:38
    版主
  • 谢谢斑竹,现在这个问题我先用另外一种方法解决掉了,就是利用ADMIN类直接由用户提交数据并搜索查询,但是这样有一些违反当初设计初衷,APPLICATION无用了。我打算尝试下你提供的第二种方法。

    2009年9月21日 1:08