我对正在阅读的书中的代码列表,Nutshell中的C#3以及线程感到困惑.在关于应用程序服务器中的线程安全的主题中,下面的代码是作为UserCache的示例给出的:
static class UserCache
{
static Dictionary< int,User> _users = new Dictionary< int, User>();
internal static User GetUser(int id)
{
User u = null;
lock (_users) // Why lock this???
if (_users.TryGetValue(id, out u))
return u;
u = RetrieveUser(id); //Method to retrieve from databse
lock (_users) _users[id] = u; //Why lock this???
return u;
}
}
Run Code Online (Sandbox Code Playgroud)
作者解释了为什么RetrieveUser方法没有锁定,这是为了避免长时间锁定缓存.
我很困惑为什么要锁定TryGetValue和字典的更新,因为即使上面的字典正在被更新两次,如果2个线程同时使用相同的未检索的id调用.
通过锁定字典读取实现了什么?
非常感谢您提出的所有意见和见解.
我有一个生产SQL-Server数据库(报告),有许多存储过程.SP以不同的方式公开暴露给外部世界
- 一些用户可以直接访问SP,一些用户
通过WebService公开
- 而另一些用户通过DCOM层封装为接口.
用户群很大,我们不确切知道哪个用户集使用哪种方法来访问数据库.
我们经常(通过每隔一个月大约1次)来自用户集的请求,通过向输出添加一列或向现有输出添加一组列来修改现有SP,所有其他保持相同.
我们最初通过修改现有SP并将新请求的列添加到输出的末尾来开始这样做.但这打破了其他一些用户群构建的自定义工具,因为他们的工具具有硬编码的列数,因此添加列意味着他们也必须修改他们的工具.
此外,对于某些列,需要复杂逻辑才能将该列放入报告中,这意味着SP性能下降,影响所有用户 - 甚至是那些不需要新列的用户.
我们正在考虑各种解决方法:
通过添加标志作为默认参数来更新现有SP并控制新功能,以控制代码路径.通过使用默认参数,如果Parameter的值设置为true,则仅调用新功能.默认情况下,它设置为False.
优点
坏处
将为任何更改SP的签名(输入/输出)的要求创建新的存储过程.
新的SP将为现有的东西调用原始存储过程,并在其上添加新需求的逻辑.
优点
坏处
执行计划是否会根据添加新参数而更改?如果是,那么这可能会对未请求新列的用户产生负面影响.
考虑到SP是数据库的公共接口,如果选择2,接口应该是不可变的?
什么是最佳做法,还是取决于具体情况,选择期权时应该是主要的驱动因素?
提前致谢!
我有一个需要支持拖放的自定义应用程序.在我的应用程序中拖动网格时,在其DoDragDrop方法中,我提供了要以序列化格式删除的对象.
当丢弃到我的某个应用程序时,它可以取消选择字符串并创建对象.
我想要做的是允许源应用程序也能够放入NotePad/TextPad.我可以看到我可以将文件从Windows资源管理器拖放到记事本,但是无法将纯文本拖放到NotePad.猜猜它检查DragEnter事件中的DataFormat并禁止字符串,但允许将文件放入其中.
提前致谢!