我想知道如何正确定义一个类并安全地使用它。我的意思是当每个网站访问者进行数千个并发呼叫时安全线程。
我做了类似下面的事情,但我想知道它是否正确构建
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];
}
}
字典只会被初始化一次。暂无添加删除更新。
答案 0 :(得分:3)
快速查看代码,在我看来,您的第一个问题是公开的字典dicAuthorities
。字典不是线程安全的。根据您对该词典的要求,您需要实现一些管理对它的访问。请参阅此相关问题:
答案 1 :(得分:3)
Dictionary支持线程安全读取。以下是MSDN的证明:
字典可以同时支持多个读者, 只要集合没有被修改。即便如此,列举 通过集合本质上不是一个线程安全的过程。在 枚举与写访问争用的罕见情况 必须在整个枚举期间锁定集合。允许的 多个线程可以访问的集合,用于读写 你必须实现自己的同步。
所以,如果你打算只从中读取数据,它应该可以工作。但是,我不相信您的词典只填充一次,并且在您的申请工作期间不会被修改。在这种情况下,此线程中的所有其他人都是正确的,有必要同步访问此字典,最好使用ConcurrentDictionary对象。
现在,我想谈谈设计本身。如果您想在用户之间存储共享数据,请使用专为此目的而设计的ASP.NET Cache。
答案 2 :(得分:3)
正如其他人所说,Dictionary<TKey,TValue>
本质上不是线程安全的。但是,如果您的使用方案是:
比你应该没事。
但是,如果您使用.net 4.5,我建议使用ReadOnlyDictionary
因此,您的实现可能看起来像这样(将编码风格更改为更友好的C#)
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);
}
我还在声明本身添加了一个readonly
修饰符,因为这样你就可以确保它不会在运行时由另一个字典替换。
答案 3 :(得分:2)
不,您的代码不是线程安全的。
附注:尝试遵循C#的编码指南并调用以大写MySpecialClass开头的类,并且具有反映类的目的的名称(或明确的示例名称)。
编辑:我的大部分要点都不适用,因为字典的唯一初始化是静态构造函数。从线程安全的角度来看,这使得初始化安全。 请注意,静态构造函数内的初始化将在“首次使用前”的非确定性时刻发生。它可能导致意外行为 - 即,当访问DB时可能使用错误的“当前”用户帐户。
答案 4 :(得分:0)
你的问题的答案是否定的,它不是线程安全的。 Dictionary
不是线程安全的集合。如果要使用线程安全字典,请使用ConcurrentDictionary。
除此之外,很难说你的csPublicFunctions
是否是线程安全的,因为它取决于你在DbConnection.db_Select_DataTable
答案 5 :(得分:0)
仅公共Dictionary
没有线程安全问题。
是的,字典填充是线程安全的。但是这个字典的另一个修改不是线程安全的。如上所述 - ConcurrentDictionary
可以提供帮助。
您的类clsUserTitles
的另一个问题也不是线程安全的。
如果clsUserTitles
仅用于阅读,则可以将每个属性设置器clsUserTitles
设为私有。并从clsUserTitles
构造函数初始化这些属性。