我正在尝试进行一些数据访问优化,并且我遇到了一个字典似乎以一种不可能的方式失去同步的情况,除非我以某种方式进入多线程情况而不知道它。
一列GridLabels绑定到一个执行数据访问的属性 - 这有点贵。但是,多行最终会进行相同的调用,因此我应该能够通过稍微缓存来解决传递中的任何问题。
然而,在应用程序的其他地方,这个相同的代码以缓存不合适的方式调用,我需要一种方法来按需启用缓存。所以我的数据绑定代码如下所示:
OrderLabelAPI.MultiSyringeCacheEnabled = True
Me.GridLabels.DataBind()
OrderLabelAPI.MultiSyringeCacheEnabled = False
缓存发生的昂贵调用如下所示:
Private Shared MultiSyringeCache As New Dictionary(Of Integer, Boolean)
Private Shared m_MultiSyringeCacheEnabled As Boolean = False
Public Shared Function IsMultiSyringe(orderLabelID As Integer) As Boolean
If m_MultiSyringeCacheEnabled Then
'Since this can get hit a lot, we cache the values into a dictionary. Obviously,
'it goes away after each request. And the cache is disabled by default.
If Not MultiSyringeCache.ContainsKey(orderLabelID) Then
MultiSyringeCache.Add(orderLabelID, DoIsMultiSyringe(orderLabelID))
End If
Return MultiSyringeCache(orderLabelID)
Else
Return DoIsMultiSyringe(orderLabelID)
End If
End Function
这是MultiSyringeCacheEnabled属性:
Public Shared Property MultiSyringeCacheEnabled As Boolean
Get
Return m_MultiSyringeCacheEnabled
End Get
Set(value As Boolean)
ClearMultiSyringeCache()
m_MultiSyringeCacheEnabled = value
End Set
End Property
非常非常罕见(不可复制的罕见......)我会得到以下异常:字典中没有给定的密钥。
如果仔细查看缓存代码,那是不可能的,因为它首先要确保密钥存在。如果DoIsMultiSyringe篡改字典(显式或通过设置MultiSyringeCacheEnabled),这也可能导致问题,并且有一段时间我认为这必须是罪魁祸首。但事实并非如此。我已经多次仔细检查过代码了。我会在这里发布它,但它会进入比适当的更深的对象图。
因此。我的问题是,datagridview数据绑定实际上是否会进入某种导致字典占用的zany多线程情况?我错过了共享成员的某些方面吗?
我实际上已经将项目代码从项目中拉出来了,但我想了解我所缺少的内容。谢谢!
答案 0 :(得分:1)
由于这是ASP.NET,因此您有一个隐式多线程方案。您正在使用共享变量(请参阅What is the use of a shared variable in VB.NET?),这是(如关键字所示)跨多个线程(来自访问该网站的不同人员)“共享”。
您可以非常轻松地拥有一个访问者的帖子到达此处的场景:
'Since this can get hit a lot, we cache the values into a dictionary. Obviously,
'it goes away after each request. And the cache is disabled by default.
If Not MultiSyringeCache.ContainsKey(orderLabelID) Then
MultiSyringeCache.Add(orderLabelID, DoIsMultiSyringe(orderLabelID))
End If
' My thread is right here, when you visit the site
Return MultiSyringeCache(orderLabelID)
然后你的线程进入这里并取代我的线程:
Set(value As Boolean)
ClearMultiSyringeCache()
m_MultiSyringeCacheEnabled = value
End Set
然后我的线程会在你清除之后尝试从字典中读取一个值。
那就是说,我不确定您对每个请求清除的“缓存”有什么样的性能优势。看起来你应该简单地不要让这个变量共享 - 使它成为一个实例变量 - 任何访问它的用户请求都有自己的副本。