字典在数据绑定期间表现奇怪

时间:2012-06-14 14:20:57

标签: asp.net multithreading caching data-binding dictionary

我正在尝试进行一些数据访问优化,并且我遇到了一个字典似乎以一种不可能的方式失去同步的情况,除非我以某种方式进入多线程情况而不知道它。

一列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多线程情况?我错过了共享成员的某些方面吗?

我实际上已经将项目代码从项目中拉出来了,但我想了解我所缺少的内容。谢谢!

1 个答案:

答案 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

然后我的线程会在你清除之后尝试从字典中读取一个值。

那就是说,我不确定您对每个请求清除的“缓存”有什么样的性能优势。看起来你应该简单地不要让这个变量共享 - 使它成为一个实例变量 - 任何访问它的用户请求都有自己的副本。