Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 正确的类定义和用法-线程安全-ASP.net_C#_Asp.net_C# 4.0_Thread Safety_Static Functions - Fatal编程技术网

C# 正确的类定义和用法-线程安全-ASP.net

C# 正确的类定义和用法-线程安全-ASP.net,c#,asp.net,c#-4.0,thread-safety,static-functions,C#,Asp.net,C# 4.0,Thread Safety,Static Functions,我想知道如何正确定义一个类并安全地使用它。我的意思是,当每个网站访问者同时拨打数千个电话时,线程是安全的 我给自己做了一个像下面这样的东西,但我想知道它是否正确建造 public static class csPublicFunctions { private static Dictionary<string, clsUserTitles> dicAuthorities; static csPublicFunctions() { dicAut

我想知道如何正确定义一个类并安全地使用它。我的意思是,当每个网站访问者同时拨打数千个电话时,线程是安全的

我给自己做了一个像下面这样的东西,但我想知道它是否正确建造

public static class csPublicFunctions
{
    private static Dictionary<string, clsUserTitles> dicAuthorities;

    static csPublicFunctions()
    {
        dicAuthorities = new Dictionary<string, clsUserTitles>();
        using (DataTable dtTemp = DbConnection.db_Select_DataTable("select * from myTable"))
        {
            foreach (DataRow drw in dtTemp.Rows)
            {
                clsUserTitles tempCLS = new clsUserTitles();
                tempCLS.irAuthorityLevel = Int32.Parse(drw["Level"].ToString());
                tempCLS.srTitle_tr = drw["Title_tr"].ToString();
                tempCLS.srTitle_en = drw["Title_en"].ToString();
                dicAuthorities.Add(drw["authorityLevel"].ToString(), tempCLS);
            }
        }
    }

    public class clsUserTitles
    {
        private string Title_tr;
        public string srTitle_tr
        {
            get { return Title_tr; }
            set { Title_tr = value; }
        }

        private string Title_en;
        public string srTitle_en
        {
            get { return Title_en; }
            set { Title_en = value; }
        }

        private int AuthorityLevel;
        public int irAuthorityLevel
        {
            get { return AuthorityLevel; }
            set { AuthorityLevel = value; }
        }
    }

    public static clsUserTitles returnUserTitles(string srUserAuthority)
    {
        return dicAuthorities[srUserAuthority];
    }
}
公共静态类csPublicFunctions
{
私有静态字典权限;
静态csPublicFunctions()
{
diauthorities=新字典();
使用(DataTable dtTemp=DbConnection.db\u Select\u DataTable(“Select*from myTable”))
{
foreach(数据行中的数据行drw)
{
clsUserTitles tempCLS=新clsUserTitles();
tempCLS.irAuthorityLevel=Int32.Parse(drw[“Level”].ToString());
tempCLS.srTitle_tr=drw[“Title_tr”].ToString();
tempCLS.srTitle_en=drw[“Title_en”].ToString();
添加(drw[“authorityLevel”].ToString(),tempCLS);
}
}
}
公共类许可证
{
私有字符串标题;
公共字符串sru-tr
{
获取{return Title_tr;}
设置{Title_tr=value;}
}
私有字符串标题;
公共字符串sru-en
{
获取{return Title_en;}
设置{Title_en=value;}
}
私人int AuthorityLevel;
公共内部irAuthorityLevel
{
获取{return AuthorityLevel;}
设置{AuthorityLevel=value;}
}
}
公共静态clsUserTitles returnUserTitles(字符串srUserAuthority)
{
返回diauthorities[srUserAuthority];
}
}

字典将仅初始化一次。以后不再添加或删除更新。

快速查看您的代码,在我看来,您的第一个问题将是公开可用的词典
diauthorities
。字典不是线程安全的。根据您想对该词典做什么,您需要实现一些规范对其访问的功能。见这一相关问题:


您的问题的答案是否定的,它不是线程安全的<代码>字典不是线程安全的集合。如果要使用线程安全字典,请使用


除此之外,很难说您的
csPublicFunctions
是否是线程安全的,因为这取决于您在调用
DbConnection.db\u Select\u DataTable
字典时如何处理数据库连接。以下是来自以下方面的证据:

一本词典可以同时支持多个读者, 只要集合未被修改。即便如此,列举 通过集合本质上不是线程安全的过程。在里面 枚举与写访问争用的罕见情况是 在整个枚举过程中必须锁定集合。允许 要由多个线程访问以进行读写的集合, 您必须实现自己的同步

因此,如果您计划只从中读取数据,它应该可以工作。然而,我不相信你的字典只填写了一次,也不会在你的申请工作中被修改。在这种情况下,该线程中的所有其他人都是正确的,有必要同步对该字典的访问,最好使用该对象


现在,我想就设计本身说几句话。如果要在用户之间存储共享数据,请使用专门为此目的而设计的。

正如其他人所说,
字典本身并不是线程安全的。但是,如果您的使用场景是:

  • 启动时填写字典
  • 在应用程序运行时将该字典用作查找
  • 切勿在启动后添加或删除值
  • 你应该会没事的

    但是,如果您使用.NET4.5,我建议使用

    因此,您的实现可能是这样的(将编码样式更改为更为C#友好)

    私有静态只读只读复制权限;
    静态公共函数()
    {
    Dictionary authoritiesFill=新建字典();
    使用(DataTable dtTemp=DbConnection.db\u Select\u DataTable(“Select*from myTable”))
    {
    foreach(数据行中的数据行drw)
    {
    UserTitles userTitle=新的UserTitles
    {
    AuthorityLevel=Int32.Parse(drw[“Level”].ToString()),
    TitleTurkish=drw[“Title_tr”].ToString();
    TitleEnglish=drw[“Title_en”]。ToString();
    }
    authoritiesFill.Add(drw[“authorityLevel”].ToString(),userTitle);
    }
    }
    权限=新的只读词典(authoritiesFill);
    }
    

    我还向声明本身添加了一个
    只读
    修饰符,因为这样可以确保它在运行时不会被另一个字典替换。

    只有public
    字典
    没有线程安全问题。 是的,字典填充是线程安全的。但是这本字典的另一个修改是线程安全的。如上所述,
    ConcurrentDictionary
    可能会有所帮助

    另一个问题是类
    clsuertitles
    也不是线程安全的。
    如果
    clsuertitles
    仅用于读取,则可以将
    clsurtitles
    的每个属性设置器设置为私有。并从
    clsuertitles
    构造函数初始化这些属性。

    不,您的代码不是线程安全的

    • [编辑不适用-在静态构造函数内设置/创建]字典(如系统关闭答案所指出的)在更新时不是线程安全的。字典不是只读的,因此无法保证它不会随着时间的推移而被修改
    • [编辑不适用-在静态构造函数内设置/创建]初始化不受任何锁的保护,因此最终会在
      private static readonly ReadOnlyDictionary<string, UserTitles> authorities;
      
      static PublicFunctions()
      {
          Dictionary<string, UserTitles> authoritiesFill = new Dictionary<string, clsUserTitles>();
          using (DataTable dtTemp = DbConnection.db_Select_DataTable("select * from myTable"))
          {
              foreach (DataRow drw in dtTemp.Rows)
              {
                  UserTitles userTitle = new UserTitles
                  {
                    AuthorityLevel = Int32.Parse(drw["Level"].ToString()),
                    TitleTurkish = drw["Title_tr"].ToString();
                    TitleEnglish = drw["Title_en"].ToString();
                  }
                  authoritiesFill.Add(drw["authorityLevel"].ToString(), userTitle);
              }
          }
          authorities = new ReadOnlyDictionary<string, UserTitles>(authoritiesFill);
      }